History | Log In     View a printable version of the current page.  
Issue Details (XML | Word | Printable)

Key: LEP-2448
Type: Improvement Improvement
Status: Closed Closed
Resolution: Fixed
Priority: Minor Minor
Assignee: Jorge Ferrer
Reporter: Jose Oliver
Votes: 3
Watchers: 3
Available Workflow Actions

Review for EE
Operations

If you were logged in you would be able to see more operations.
Old Liferay Portal (Use Liferay Portal Standard Edition)

Ability to serve multiple companies/portals with just one instance of Liferay (only one webapp)

Created: 25/Mar/07 04:35 AM   Updated: 22/May/07 02:14 PM
Component/s: None
Affects Version/s: 4.2.1
Fix Version/s: 4.3.0

Original Estimate: 2 days Remaining Estimate: 2 days Time Spent: Unknown
File Attachments: 1. Zip Archive addASP-patch.zip (31 kb)
2. Zip Archive MainServlet_and_LuceneServlet.zip (8 kb)
3. Text File mass_company_virtualhost.patch (34 kb)
4. Text File mass_company_virtualhost_against_rev6391.patch (34 kb)
5. Text File mass_company_virtualhost_against_rev6391_refactored.patch (35 kb)
6. XML File struts-config.xml (83 kb)
7. XML File tiles-defs.xml (51 kb)
8. GZip Archive updates.tar.gz (38 kb)

Environment: any


 Description  « Hide
Documentation sais that Liferay is designed to be used in ASP environments, but it requires replicating the "original" webapp in other webapps (one for each company we want to serve, since company_id is a servlet parameter that gets read in a static field by all affected servlets and is used all along the way). I've made some modifications to LEP 4.2.1 in order to be able to serve as many companies/domains with just one webapp, without the need of replicating any webapp. In this way, LEP works as a "real" ASP-ready application. It shares database *and* webapp among as many companyIds as needed.

Of course, this presents some considerations that one must take into account when using this model (basically, and obviously, you have the same webapp for any of the companies configured under it, thus they use exactly the same code), but I think this is how "pure" ASP should really work and it doesn't prevent anybody for using the "classical" ASP model of LEP (replicate webapps)

The modification I've done consists, basically, in the following:

* Add a ASPVirtualHost class that reads a configuration file that maps companyIds to domains and is able to return the companyId that must be used to serve a request based on the host being accessed (this functionality, maybe, could be merged with VirtualHostUtil that LEP provides for virtual hosting throug communities).

* Modify all servlet's that "cache" company_id in static fields, and replace the static company_id usage by the company_id that is resolved by a call to the previous class.

* For many of these servlets, create a replica of init/destroy (initOtherIds/destroyOtherIds) methods, that take care of initialising/destroying "secondary" companyIds (there is always a "main" companyId that works as default, and is the company_id configured in xml configuration files)

* Minor modifications to other classes (not servlets) that cache/make use of company_id bypassing the company_id configured for each request in MainServlet or that just doesn't depend on it because they don't work as a service for a request but as background processes (for example, Lucene and it's indexers/threads)

* Add a modified version of ShellHook for mail that passes (as environment variable) the companyId to the shell hook

* Modify mailadmin.ksh to get companyId value from environment

At the moment, I'm testing these modifications to look for hidden traps in the code that are not asp-friendly, but it seems that they work pretty well, and allow even the start/stop of companies/portals on the fly (the ASPVirtualHost class has a thread that checks for modification of the configuration file and is able to make the appropiate calls to "remove"/"add" companyIds)

I think this would be a great functionallity to include in the main source tree, in order to allow anybody to have as many "sharing" ASP portals as needed (besides the fact that I'm really interested in using it without revieweing each release of LEP to make exactly the same modifications :-) )

I've the code working, and I'm willing to deliver it to (at least, as an example or proof-of concept) be included in the main source of LEP. If you are interested in it, just contact me at primijos at gmail dot com.

I'm, of course, afraid I'm maybe replicating functionalities already in the portal but not well documented, since, along my "investigation" I've found "suspicious" classes like "PortalInstances" and other config parameters (portal.ctx), etc.... but no clear documentation on how to achieve exactly the functionality I'm providing here just by using these classes/parameters

Any feedback will be, of course, welcome

Best,
       Jose

 All   Comments   Work Log   Change History   Subversion Commits      Sort Order:
Jose Oliver - 27/Mar/07 07:48 AM
This tgz contains the classes I've modified in order to support this behaviour (please, note that this is just quick code that, from my tests, seems to work, but it needs extensive testing, refactoring and the sight of some liferay core developers :) )

I hope it will serve at least as proof-of-concept

Main modifications:

* Modified some servlets to ignore static value of companyId and use a companyId based on the host name requested
       * Added class to maintain mappings from hostname/domain to company id
       * Modification on some other -non servlet- classes that also made use of a static companyId or that just take in care one companyId (for example, extending Lucene services to have one thread per company)
       * Modifications to some external systems interfaces (ex. mailadmin.ksh, made it "asp friendly" and adding a new AspShellHook that configures environment variables before invoking the shell hook to pass the company id to the script)
       * Some minor bug fixes (AspShellHook -> mailadmin.ksh interaction didn't work ok if user has spaces in the second name, inconsistences between userIds created by mailadmin.ksh and the ones used by the mail portlet, etc.)

Helmut Denk - 10/Apr/07 05:55 PM
im not sure about youre idea. some things will work
different: concurrent use of servlet-context, only one
set of war-settings (web.xml) for multiple portal-instances.

what if you want to use different filters. for instance:
portal-a uses cas(-filter) and portal-b dont.

we pack some additional resources to our portal-web-xxx.war.
each portal-instance can have different additional resources.
we would have to be more careful with this things ... use
some naming-convention ... hmmm ...

may be your plan are ok though ... handle with care ;-)

atul patel - 15/Apr/07 06:52 PM
This is a great idea. I've run into the same exact issue. At the moment, I'm just working around the issue since I'm providing mostly community functionality to users. That said, my intentions were to do exactly what you are doing (when I got time). It seams strange that this wasn't already done. I can see a great deal of ASP applications that could benefit from your changes. A HUGE benefit with your changes I see is system resources. I haven't done any tests to see how much each portal "costs" but I do believe it adds up very quickly.

As to Helmut's comment, I understand what he is getting at but I think is a situation where it depends on the application.

In the ASP model I use, each customer would have similar functionality and just need their data properly scoped (which is what we are using the company id to do).

I'll try your code out this week and see what happens. Any word from seasoned developers?

Jorge Ferrer - 16/Apr/07 12:32 AM
Hi Atul,

I'm planning to take a look at the patch later this week or early next week. One of the first things I want to do is to see if the current functionality used by some, as Helmut, is kept.

If you can download and apply the patch, test it and help fixing any issues that you find that would be helpful.

Jose Oliver - 24/Apr/07 10:56 AM
Well, as Helmut says (and, I think, I also pointed out in some comment), there would be some hidden places where a deeper look would be recommended :)

Of course, as long as this modifications result in serving N portal instances with just one webapp instance, the main implication is that all those N portal instances are sharing the same war settings. That would be a problem in some situations.. but.. if you need different instances to have "personalized" war settings you always can fall back to the "old" or "original" ASP model (1 instance <-> 1 webapp) or group instances in sets that share the same war settings and deploy those instances in separated weapps.

Of course, a more sofisticated solution would be ok, but I think that solution diverges from my main objective when developing the modifications. I was thinking about sharing a webapp among different portal instances that *actually* didn't need war specific configurations (that is: they share datasources and all other stuff defined in the war configuration -being filters one of these settings?). This would result in the possibility of ASP deployments where the only possible per-company configurations are those available in portal.properties, by means of portal-companyId.properties files (and this actually works, as far as I've tested).

I've not taken a detailed look of the possibilities available by means of war settings configuration, but I guess that it would not be so easy to "move" to application level, as long as they are strongly related to a "classic" weapp concept, and what I was proposing, actually, was to have N portals (companyId instances) as 1 webapp. As you see... 1 webapp -> 1 war settings (in the originaly idea).

Anyway, I think this would be an interesting discussion. I'll take a look to it but I think that the core developers would be able to expose arguments much more founded and stronger than mine (basically, by knowledge of the software).

And remember... anybody needing war-specific settings can always fall back to the 1 portal <-> 1 webapp model :)

There's also another issue that Helmut points out in it's comment, and it's the concurrent use of servletContext. To be honest, I didn't realise that... I was making an "optimistic approach". I'll take a deeper look at it, and I hope concurrent access would be OK... actually, concurrent access to it should be already expected and well managed, as long as it is shared by different requests. I'm assuming you are afraid about some not "companyId-alized" behaviours around it?

atul patel - 25/Apr/07 03:47 AM
I'll be happy to help out. I've been a bit swamped and haven't had a chance to try out the patch yet. Hopefully will get to it today.

--atul

Mika Koivisto - 26/Apr/07 05:25 AM
This is really great feature. I hope this makes into LEP 4.3 even if its in just experimental stage. Currently we are using virtualhosted communities but there the problem is that you can't limit the visibility of other communitys users to other communities.

atul patel - 08/May/07 08:01 PM
Hi all.

So I've been working on this for the last couple of days. Here is a summary of where I am so far...

I've created a VERY basic and PRELIMINARYY portlet addition to enterprise admin that will add and search for "subcompanies".

This basically creates an a company and sets it associated account's parentaccount to the accountid of the current logged in company/site.

It then uses checkCompany to create the default records. I then create a community in the new company with the same name as the company. It still needs layouts.

I've modified VirtualHostFilter to convert the virtualhost into a companyId that is set as an attribute on the request object.

My next step is to convert the remaining references to the company object to come from the request instead of from the portal context and then test...

There is still a lot to be done regarding the initialization routines, and validating the change.

I'm new to portlets/struts and was wondering if anyone would like to collaborate... I think the new accounts tab under enterprise admin should be modified to include all the subtabs that are avaiable below settings in the admin portlet.

I'll let you all know how it goes..

Thanks guys for the great application and for all the work toward converting the IDs to longs


atul patel - 08/May/07 08:04 PM


just remembered. A cool (IMHO) connection I made is that when the community for the new company is created, its layoutSet's virtualHost is automatically populated based on the portal url for the company -- perhaps others have made this connection -- any thoughts on why this shouldn't be done.

Jorge Ferrer - 09/May/07 12:44 AM
Hi Atul,

Thanks for your work on this. I have a question, is your work based on the patch provided by Jose Oliver? Based on your description it seemed to me that you are following a different approach.

atul patel - 09/May/07 12:53 AM

So I had written an epic comment, but then clicked attach multiple files and lost all of it... aargh.

I've attached 2 subversion patches, and my struts and tiles def files.. The patches are based on Rev 6202.

It needs LOTS of TESTING, but it does work in adding child companies, and rendering them based on community virtual hosting. When adding a company I used the portaURL to determine a virtualhost name.

Here are the assumptions I made to get this to work...
1. It is safe to attach the companyID to the request attribute during the virtualhostfilter
2. It is safe to iterate across the initializations within mainservlet for each company
3. It is safe to get companyid from the requestAttribute and use it to define the company context in all cases
4. It is safe to determine the companyid based on the layoutset's virtual host matching the request's hostname (i guess this is the really important assumption)

I also created a very very preliminary tab in the enterprise admin portlet.. It works but gives an error message at the end.. Can someone help with creating a better portlet / copying the Admin/Settings subtabs to the new Accounts tab in EnterpriseAdmin. We probably need to also add a new permission called Add Company.. The webid needs to be of the .com/.net, etc variety because the admin email address is created based on this. The additional tab allows additon of new companies.

My comments can be found by searching for atul in the code

I forgot what else I had originally wrote, but if you have questions, please email me... or skype at atul.harbor9. I'd love to collaborate with someone to make this production ready.

Thoughts.... Feedback please...

Jorge Ferrer - 09/May/07 02:39 AM
Hi Atul,

Thanks for your patches. I (or someone else from Liferay) ll have a look at it, although it'll have to wait until 4.3 is released because this is a big change that would have the effect of delaying the release a lot. I hope that's ok with you.

Also it would be great if you and Jose could coordinate/integrate both approaches.


atul patel - 09/May/07 03:45 AM
On 5/9/07, Atul Patel <atul@harbor9.com> wrote:
I had compared your code to the existing code to get an idea of what
you were doing, but the actual code itself is all fresh...

Yes, I've seen the patch and lots of code there! :)

In my scenario, I believe in zero filesystem access to run services.

That's my ideal scenario also, but since LEP uses a bunch of
properties from system/portal.properties, I didn't go that way. I
agree with you in the sense that, as long as it seems, everything
should be able to be managed from UI

Everything should be provisionable and controllable from the
interface. That said, a few UI portlets will need to be made

I think this would be basically: extending admin portlet (as
you suggested) to allow omniadmin/admins/people-with-permission to
create/manage/remove companyIds and a "little" extension to allow to
manage .properties for each company by using the UI. These are
modifications in "UI land only".

(something I need to find help on.) My scenario basically has my
master company creating children companies with the potential that
those children companies may create their own (but that is way in the

Seems ok

future and so need a permission system to allow me to see the add
children company and not other admins.)

That's ok also, permissions should be there

I believe (though I didn't test it) that the changes also allow for
multiple virtual hosts within any single company.

I think they should be compatible. In my approach, I'm able to
associate *.mydomain.tld to a companyId, so I don't see why it
shouldn't work with domain1.mydomain.tld,domain2.mydomain.tld, etc.

I use the "virtual hosting" mechanism to essentially accomplish the
same thing as I believe you are trying to do without additional
overhead of a secondary properties file to manage. This allows the

I think we're also pursuing the same objective (sharing a
webapp among different instances). For me, having a secondary property
file was not a big overhead, since companyIds are not
created/destroyed every second :) Anyway, having everything available
from the UI could be great.

system to be very dynamic... It would be nice to add a properties
portlet that would configure the properties for each company.

I think that's one of the key points. Moving companyIds
management to top level (UI) seems reasonable only as long as you also
provide tools to manage *everything* and I think the only thing
missing there are those in portal-XXX.properties.

Because of the iteration on multiple companies during the init, I
believe a performance issue may occur once hosting many sites... I
haven't run any metrics to determine the "cost" of each additional
company.

I have run very simplistic tests, and a 60-instances startup
with my modified version has no noticeable (maybe 5-10 seconds, a
total of around 40 seconds) overhead. Having this 60-instances with
the native approach (separated weabpps) would have been... don't
know... maybe 30/45 minutes? **minimum**

I wonder if we are both trying to achieve the same goals... perhaps

Maybe. As I've told, I want to be able to have *one* webapp
serving *many* companyIds. I'm starting up a little bussines based on
Liferay ASP hosting (offer Portal [company] instances to end users,
without worrying about installation, upgrades, backups, etc.), so I
want to maximize resources usage. Basically, this is a next-level
service compared with RimuHosting Liferay Hosting (I think).

What are your goals?

we should talk and find a way to divide the work and share the
results... :)

It would be great... I'm finishing the setup of the site, so
I'll launch the service using my approach, in order to have it up and
running asap, but afterwards I'll able to collaborate with you and the
Liferay guys in order to integrate the ASP model support inside
liferay.

Thanks for the fast response, I can't wait to hear the good and the
bad (please) about the changes... don't worry about hurting my
feelings, I just want to improve the product.

Ok, we'll continue talking. I've seen Jorge has answered but I
can't read the response now (going late to a meeting :) ), I'll
continue later.

Best,
      Jose

Jose Oliver - 09/May/07 07:12 AM
Do you think we shoud start to write down a little design doc / concept doc / whatever, in order to list what we think LEP needs to support pure ASP and how to support it? Maybe we can use the "liferaypedia"? don't know... I think that some involvement from someone in the Liferay core team would be great, since there are som architectural issues that need to be reviewed by someone with a global scope

Jorge Ferrer - 09/May/07 09:12 AM
Hi Jose,

That's a very good idea, I've created a new page in the Proposed Projects section of LiferayPedia about this. You can find it here:

http://wiki.liferay.com/index.php/Dynamic_Management_of_Companies

I'll keep and eye on it and will other Liferay developers know about it once it get's more content.

Mika Koivisto - 10/May/07 02:15 PM
Since this is a feature I need I ported Jose's original patch against latest trunk. I'm hosting multiple sites with their own user base on a single server with limited memory. I did some refactoring since there was some duplicate code in Mainservlet and LuceneServlet. I hope we can coordinate our efforts through the wiki to get a solution that is good for everyone. In the mean time try this if you want it in LEP 4.3.

Jose Oliver - 11/May/07 11:15 AM
Mika, nice job.

As you point out, the modifications I submitted needed some refactoring (noticeabilly most copy/past code in MainServlet and others :) ), since they started much as a proof-of-concept than any other thing. I'm busy these days so I've not had time to get into the Wiki, but that's something I'm willing to do in the next days. And with more hope, since I see that there are some more people willing to have this feature available in next releases. How is going your experience hosting those multiple sites? Any "hidden traps" in the multicommunity patch?

Brian Chan - 19/May/07 04:05 PM
Wow. This is pretty nice stuff.

Mika, can you coordinate some "trunk" patches? Perhaps we can get this into 4.3, and if not, then in 5.0 for sure (the next release after 4.3).

Brian Chan - 19/May/07 04:40 PM
Working on merging Mika's 5/10 patch. It's actually very lean. The bulk of it is in MainServlet, VirtualHostUtil, and in LuceneServlet. Will give an update when it's completed.

Brian Chan - 19/May/07 04:49 PM
Hey Mika, I'm having some merge issues. Can you send me your MainServlet.java and your LuceneServlet.java? Thanks.

atul patel - 19/May/07 09:50 PM

Hi Brian.

What do you think about having company_ids come from the database instead of from properties files?

I'd be happy to spend some time coding for that. (Its much easier for me to replicate just a database instead of also replicating configuration files ) for backup/redundancy purposes.

-Atul

Andrius Vitkauskas - 19/May/07 10:53 PM
t's very nice that moving on something positive regarding this patch. I also need it badly .

Actually i am testing this also - to be exact, Mika's patch.
I'm testing on tomcat/winxp for now, but in few days i'm going to upgrade tomcat/LP.4.2.2 on my Linux server to LP.4.3 trunk build. For now almost everything seems to be working fine on functionality, except few issues i found in my logs.

More details on errors see in my post on forums thread http://www.liferay.com/web/guest/devzone/forums/message_boards/message/29234

Really it's killing feature, and i hope so much that it will be included in 4.3. Even if still in unadvanced stage, better it would be there, if it is not impacting any other functionality. IMHO very first thing to do it would be recheck twice about any possible issues, and don't go into advancing features to much for now, otherwise it can stretch till 5.0... Please don't do that...

About storing mappings in db , it would be great, but... not exactly now :). Current functionality is quite enough for normal work, anyway there is lots of config files which u have to backup anyway, and with storing mappings in db we will need also webUI for editing, then something else, then something more... and we will have something working without patches maybe in 6.0 :)... Please lets make first inside trunk what is working now , and improvements can be done later also. Like Atul can do already some codding nd testing, even for that can be opened one more issue or sub issue for this issue, but please don't mix it up here everything at once and delay all this nice thing till next year... Lots of coding needs lots of testing and i want things working :)

What others think on this ? i think there was more ppl who needs it working ? :)
 


Mika Koivisto - 20/May/07 02:51 AM
Brian here's my MainServlet and LuceneServlet

Mika Koivisto - 20/May/07 09:31 AM
Here is my original patch updated against latest revision (6391) in trunk

Mika Koivisto - 20/May/07 10:28 AM
Refactored my latest patch a bit. Instead of using a thread to poll the config file I moved it to use JobScheduler.

Ultimately I think we should use database to hold the config but that is something that should be done for 5.0. I'd rather see 4.3 with this properties file based confg than delay 4.3 release.

Jose Oliver - 20/May/07 01:55 PM
Nice to see all this movement around this issue!!

I agree with Mika and Andrius regarding the db usage for dns->companyId mapping. I think it would be great to have the main functionality in the 4.3 and that the db usage for that mappings could waint until 5.0. Actually, there are some other issues that need to be addressed in order to have a full "GUI-managed" ASP setup. Actually, despited all the mappings were managed using the GUI and stored/retrieved from DB, many other configuration setup would still require command line access in order to customize instances. For example: mailhook to use ("real" or "dummy"), languages for each portal, etc. (I have a list that I use for each host I include in my asp services, so maybe I can review it when I have access to my hosts and include it here). All this is related with the possibility of "moving" some .properties configurations onto GUI-space for full-GUI-manageable companies.

After having the main functionality (multiple companyIds, mappings obtained from properties file) inside the core, I think we can take some time to discuss the best strategy to get all this manageable from the admin UI (look at the wiki page, I think there are many thinks to take in consideration), make it fully-compatible with VirtuaHostingThroughCommunities, etc.

Brian Chan - 22/May/07 02:06 PM
See LEP-2794 - I had to remove EJB support to make this easier to do, and have it work in every app server environment.

Props goes out to everyone who helped out with this issue.

Go to the Admin portlet -> Go to Instances

You can add new companies via the GUI now.

This has been tested with Community Virtual Hosting AND enterprise/company/portal instance virtual hosting.

You can now add companies and communities on the fly.

Brian Chan - 22/May/07 02:09 PM
Had to make multiple commits because of SF.net SVN choking when it's too many files.

See revision 6408 to 6416.

Brian Chan - 22/May/07 02:14 PM
See LEP-2795 as well on simplified deployment process.