multiple company_ids, just *one* portal instance on one tomcat???

16246, modified 19 Years ago. Junior Member Posts: 73 Join Date: 8/1/05 Recent Posts
Hi all,

I'm doing some testing on virtual hosting (asp hosting actually) using version 4.2.1. First of all, I've found that following the wiki instructions for 4.1 doesn't work anymore for 4.2.1 (at least with jdk1.5, tomcat 5.5.17 on linux). I get lots of errors about struts forwarding and neither the original instance nor the new virtual hosts work emoticon

Anyway... beside this issue, on the general ASP design: looking around the instructions I find a great drawback having to replicate each time, for each virtual host, the binary of the portal (all the contents of the webapp). I'm not sure wether this means that classes in each webapp get loaded twice in memory (if not, why copy them instead of just changing the appropriate docroot, etc. in the config file?). If this is true, then one would need *tons* of memory just to have two or three instances in one tomcat (sure this gives flexibility to have different implementations of some classes in each instance but... who really needs this? and, if you need this, you can deploy to a separate tomcat instance)

Besides that, there is also a increase in disk usage, but my main concern is, obviously, memory compssumption. Can anybody confirm that this is true?

With this concern in mind, I've taken a look to the sources just to check wether it will be possible to modify it in order to support multiple portals (differnt company_ids) just with one instance of liferay.

Most of the code is aware of companyId by retrieving it from the request/session/wherever so, the point is that, maybe, with some modifications to some *important* classes, one will be able to have different company_ids sharing all the memory.

A kick look at the code that uses the init parameter company_id show us that:

[
root@primijos ~]#  find . -name "*.java" -exec grep '.getInitParameter("company_id")' {} \; -print
                        _companyId = ctx.getInitParameter("company_id");
./Software/Liferay-4.2.1-src/portal-ejb/src/com/liferay/portal/cms/servlet/CMSServlet.java
                                ctx.getInitParameter("company_id"));
./Software/Liferay-4.2.1-src/portal-ejb/src/com/liferay/portal/deploy/HotDeployPortletListener.java
                _companyId = ctx.getInitParameter("company_id");
./Software/Liferay-4.2.1-src/portal-ejb/src/com/liferay/portal/servlet/filters/autologin/AutoLoginFilter.java
                        _companyId = ctx.getInitParameter("company_id");
./Software/Liferay-4.2.1-src/portal-ejb/src/com/liferay/portal/servlet/filters/layoutcache/LayoutCacheFilter.java
                _companyId = _ctx.getInitParameter("company_id");
./Software/Liferay-4.2.1-src/portal-ejb/src/com/liferay/portal/servlet/filters/virtualhost/VirtualHostFilter.java
                        _companyId = ctx.getInitParameter("company_id");
./Software/Liferay-4.2.1-src/portal-ejb/src/com/liferay/portal/servlet/FriendlyURLServlet.java
                        _companyId = ctx.getInitParameter("company_id");
./Software/Liferay-4.2.1-src/portal-ejb/src/com/liferay/portal/servlet/ImageServlet.java
                        _companyId = ctx.getInitParameter("company_id");
./Software/Liferay-4.2.1-src/portal-ejb/src/com/liferay/portal/servlet/LuceneServlet.java
                        _companyId = ctx.getInitParameter("company_id");
./Software/Liferay-4.2.1-src/portal-ejb/src/com/liferay/portal/servlet/MainServlet.java


Taking a look at this clases, you could find that most of them just initialise, in its init method, some internal variable (_companyId) to the value of the init parameter in order to use it later. This could be easilly changed to perform lookup of the appropriate company_id to use based on virtual host name.

There are, however, some others that present other problems, like these:

* LuceneServlet: creates and keeps track of a thread for the company. It's behaviour should be changed to instantiate as many threads as companies (in order to keep the thread code as is)

* MainServlet: the big deal... its init(), of course, keeps track of portal-wide initialisation. It should be reworked to perform this initialisation for each of the companyIds you want to manage with this single instance. This seems doable, but the main problem, maybe, is that it sets attributes in the Portal Context (ctx.setAttribute(WebKeys.COMPANY_ID, _companyId) for example).

I know that there are a lot of "if" here but, anybody sees any big problem to stop doing this modifications in order to have multiple company_ids with just an instance of the portal? (mainly...you guys at Liferay.com, any hint will be appreciate)

Best,
Jose
16246, modified 19 Years ago. Junior Member Posts: 73 Join Date: 8/1/05 Recent Posts
Hi guys,

I have a working (at least, with some basic testing) prototype of the idea I exposed in the previous post. Modified files:

./portal-ejb/src/com/liferay/portal/cms/servlet/CMSServlet.java
./portal-ejb/src/com/liferay/portal/servlet/filters/autologin/AutoLoginFilter.java
./portal-ejb/src/com/liferay/portal/servlet/filters/layoutcache/LayoutCacheFilter.java
./portal-ejb/src/com/liferay/portal/servlet/filters/virtualhost/VirtualHostFilter.java
./portal-ejb/src/com/liferay/portal/servlet/FriendlyURLServlet.java
./portal-ejb/src/com/liferay/portal/servlet/ImageServlet.java
./portal-ejb/src/com/liferay/portal/servlet/LuceneServlet.java
./portal-ejb/src/com/liferay/portal/servlet/MainServlet.java
./portal-ejb/src/com/liferay/portal/util/VirtualHostingUtil.java

The last is a new class that keeps track of company_ids managed by one instance of the webapp and also of DNS -> company_id mappings. Maybe it should be better called "ASPHostingUtil" or similar, or just merged into VirtualHostFilter...

On the other side, there are some other classes that make use of the "company_id" parameter or that just have the string "company_id" inside but, as long as it seems, doesn't need to be modified (I think):

./portal-ejb/src/com/liferay/portal/deploy/HotDeployPortletListener.java
./portal-ejb/src/com/liferay/portal/security/auth/LDAPAuth.java
./portal-ejb/src/com/liferay/portal/tools/PortletDeployer.java
./portal-ejb/src/com/liferay/portlet/journal/util/ContentTransformerListener.java
./portal-ejb/src/com/liferay/portlet/journal/util/JournalUtil.java
./portal-ejb/src/com/liferay/portlet/journal/util/JournalVmUtil.java
./portal-ejb/src/com/liferay/portlet/journal/util/PropertiesTransformerListener.java
./portal-ejb/src/com/liferay/portlet/journal/util/URIResolver.java

Should I look for other "non-asp-friendly" means of getting the companyId? (greping ctx.getAttribute(WebKeys.COMPANY_ID reveals only MainServlet and PortletConfigImpl)

Of course, it has some drawbacks (same classes/jsps for all companies sharing this instance) but I think that's a minor issue (and it's not mandatory to use this model of ASP hosting), and it gives flexibility to host many companies in the same instance of the same webapp (no need to replicate, configure wirtual host in tomcat, etc.).

Also: startup of one tomcat with two virtual hosts, one for each instance of liferay is -for me- about 240 seconds, and this case also yields some issues like, for example, Alfresco being initalised twice (one for each virtual host); startup time for the modified version serving 9 (nine!) companies is about 120-140 seconds.

Any chances to get this functionality (either with my or yours implementation) in the source code for next releases? I like hacking sometimes, but I think it would be great to have this flexibility maintained inside the original distribution of Liferay

Best,
Jose
30371, modified 19 Years ago. New Member Post: 1 Join Date: 3/15/07 Recent Posts
Hi Jose,

First thanks for the great analysis info. I had been considering trying to make a similar change to liferay as I think the single instance approach to ASP implementation would suit the needs of my project better than either multiple instances or community-based virtual hosts. I had not yet gotten to the point of actually making any code changes along these lines though.

Have you gotten any feedback from the liferay team about possibly incorporating this into the codebase?

I would be really interested in taking a look at your code changes and possibly using them as a starting point rather than redoing what you have already done... would it be possible to get you to send me the files you had to add or change? You can email me at liferay@noteric.com.

Maybe having more than one person playing with this and testing it could be of some use as well?

Thanks again,
Eric
thumbnail
10437, modified 19 Years ago. Liferay Legend Posts: 2871 Join Date: 8/31/06 Recent Posts
Hi Jose,

This sounds very well. I'll take a look at it as soon as time permits.

Eric, if you can help testing it and finding potential drawback it would save me a lot of time.

Thanks emoticon
28101, modified 19 Years ago. New Member Posts: 16 Join Date: 12/19/06 Recent Posts
Hi!

We've been trying this out for a few days and it really looks great. Hope you can make this available in the 4.3 release or later.

Good job!!!emoticon
thumbnail
10437, modified 19 Years ago. Liferay Legend Posts: 2871 Join Date: 8/31/06 Recent Posts
Thanks for your input Per. It helps!
16246, modified 19 Years ago. Junior Member Posts: 73 Join Date: 8/1/05 Recent Posts
Hi Per,

thanks for your beta testing emoticon Could you, please, provide some feedback about it? How many instances are you deploying in each webapp? High load? Concurrent access works OK? Memory usage is ok for you? etc.

Of course... if you have time to do it emoticon

Best,
Jose
thumbnail
14911, modified 19 Years ago. Expert Posts: 484 Join Date: 3/2/06 Recent Posts
Hi Jose,

Does this approach use the same database instance for all the companys.. or is there a way have a different database usage per company.

Also, do u plan to get the company id from the url as opposed to web.xml as it happens now.

Also, does your solution enable distinct home page/guest page for each company.

I see your approach as though full architectural solution to asp hosting feature.

In this regard, I see liferay supports some kind of organizational higherachy.. could the same approach be taken to have company id as the parent of each organization etc..as alternate approach support mutile companies.

Regards,
Raja Nagendra Kumar,
C.T.O
www.tejasoft.com
16246, modified 19 Years ago. Junior Member Posts: 73 Join Date: 8/1/05 Recent Posts
Raja Nagendra Kumar:
Hi Jose,

Does this approach use the same database instance for all the companys.. or is there a way have a different database usage per company.


Hi Raja,

this approach uses the same database instance for all companyIds in the same webapp (as long as the database datasource is defined at webapp level). I think you need different webapps in order to have separated databases.

Also, do u plan to get the company id from the url as opposed to web.xml as it happens now.


Yes, companyId is retrieved based on the hostname accessed by the request. There exists a companyId -> hostname(s) mapping in a properties file that allows you to serve the same ID for multiple domains

Also, does your solution enable distinct home page/guest page for each company.


Yes. It just shares one webapp between different companyIds, so each companyId can have exactly the same configuration and possibilites (distinct home pages, etc.)

I see your approach as though full architectural solution to asp hosting feature.


Well, I hope so, since I'm willing to offer Liferay ASP hosting services in an easy/cheap way ;-)

In this regard, I see liferay supports some kind of organizational higherachy.. could the same approach be taken to have company id as the parent of each organization etc..as alternate approach support mutile companies.


I don't think it to be a trivial question... anyway, I think you don't need it, since you have separated name spaces for each company Id, each having it's own hierarchy of organisation, location, etc.

Best,
Jose
thumbnail
25246, modified 19 Years ago. Liferay Legend Posts: 1519 Join Date: 8/7/06 Recent Posts
Hi Jose!

Excellent work.

José Oliver Segura:

Also, do u plan to get the company id from the url as opposed to web.xml as it happens now.


Yes, companyId is retrieved based on the hostname accessed by the request. There exists a companyId -> hostname(s) mapping in a properties file that allows you to serve the same ID for multiple domains


Is there a reason why it is in a properties file and not in database as the the virtual host mapping for communities? This would offer greater flexibility to be able to add new companies dynamically.
29356, modified 19 Years ago. New Member Posts: 8 Join Date: 3/17/07 Recent Posts
Jose,

Can you post the code somewhere for others to test? Or can you email to me at gshester@gmail.com. We are trying to make multiple instances of liferay work and hitting many problems. It sounds like this approach would be very nice for us.

Thanks!
Greg
16246, modified 19 Years ago. Junior Member Posts: 73 Join Date: 8/1/05 Recent Posts
Greg S Hester:
Jose,

Can you post the code somewhere for others to test? Or can you email to me at gshester@gmail.com. We are trying to make multiple instances of liferay work and hitting many problems. It sounds like this approach would be very nice for us.

Thanks!
Greg


Hi Greg,

I did post all the modified classes/files in Jira:

http://support.liferay.com/browse/LEP-2448

Just download the file attached to the issue and use this files instead of the ones that came with LEP 4.2.1 (not tested yet with 4.2.2).

On the other hand, what approach were you following to get multiple instances of liferay working? what is your objective? what problems did you find?

Best,
Jose
16246, modified 19 Years ago. Junior Member Posts: 73 Join Date: 8/1/05 Recent Posts
Hi all,

I've started to add some thoughts/proposals/ideas about implementing this feature in the main source tree in the Liferaypedia:

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

Any feed/contribution will be wellcome.

Best,
Jose

---
triarium.com Liferay ASP hosting and services
thumbnail
10437, modified 19 Years ago. Liferay Legend Posts: 2871 Join Date: 8/31/06 Recent Posts
Hi Jose,

Thanx, it looks very good. One question though, the main functionality that you describe should already be implemented in the patch that you posted to LEP-2448, right?
16246, modified 19 Years ago. Junior Member Posts: 73 Join Date: 8/1/05 Recent Posts
Hi Jorge,

yes, as you said, the main functionality to implement as a "core" functionality before any GUI (admin) addition should be -from my point of view- that implemented in the patch I submited.

But notice that, after that, Atel Patul posted a patch agains the latest svn that also had improvements over my code -mainly a proof- that removed duplicated code, etc.

I think that it is very important, in this point, to have your help -Liferay team- in order to locate the "hot spots" for company initialisation/request->company mapping, company_ids caching, "bad behaved" classes, etc.

Once this points are located and we all are pretty sure that we're not forgeting any of this issues inside the core or peripherical code (i.e. the "mailadmin.ksh" case), the modification and addition of that functionalty should be only a question of adapting my patch and the revision made by Atel Patul. A hot spot here is also the hot start/stop (mainly stop?) of companies.

The only point beyond this that -I think- should be inside scope of this first step -or not, depending on what we agree- is the compatibilty with Virtual Hosting through communities.

The rest (hierarchies, gui admin tool, activation/deactivation/deletion of companies, permissions delegation, accounting and limits, etc.) must be, I think, a second phase target. This could allow us to focus on core functionality, db design, implications within the rest of the code, etc. and have a fully functional ASP-friendly Liferay implementation. After that, a GUI tool, and the rest (including "moving" some configuration parameters to db land instead of properties files land) should be straightforward.

I don't know what do you guys think. Are we going in the right path?

Best,
Jose

---
triarium.com Liferay ASP hosting and services
thumbnail
10437, modified 19 Years ago. Liferay Legend Posts: 2871 Join Date: 8/31/06 Recent Posts
Hi José,

Yes, I think this is definitely going in the right direction. And it will be one of the first things I or someone else from the core team will work on once 4.3 is released. Until then all the work on the wiki page and the submitted patches will really help.
thumbnail
30906, modified 19 Years ago. New Member Posts: 13 Join Date: 2/17/07 Recent Posts
Hi everybody,

It's very nice that moving on something positive regarding this patch. I also need it badly emoticon . 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.

First of that is with locating asp-hosts.properties on tomcat/windows, if in portal-xt.properties i am setting path in windows style:
shared.virtual.hosting.config.file=c:/dev/liferay/ext/servers/tomcat/conf/asp-hosts.properties

Then VirtualHostingUtil.loadProperties(String) is throwing exception on
URL url = new URL("file://" + _cfgFilePath);
It means i have to always specify path with starting "/", like "/c:/java/tomcat".
For now i have edited this to:
URL url = new URL("file:///" + _cfgFilePath.replaceFirst("^/",""));
, It should work on both unix/windows, but in general it's needed to review and fix this part more, as there is a little mess around it - `there is defined BUNDLE_NAME and even passed as parameter to loadProperties(...) but that parameter is not used inside method. I think it would be better to make by default file asp-hosts.properties just placeable anywhere on the classpath (like portal-ext.properties). Of course if path for this file specified explicitly in portal-xxx.properties it can override defaults.

Another thing is - when shutting down tomcat, it throws ecception about properties updating thread. Here it goes:

03:50:42,826 ERROR [VirtualHostingUtil:95] sleep interrupted
Exception while removing reference: java.lang.InterruptedException
java.lang.InterruptedException
	at java.lang.Object.wait(Native Method)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132)
	at sun.java2d.Disposer.run(Disposer.java:125)
	at java.lang.Thread.run(Thread.java:619)
03:50:42,896 ERROR [MainServlet:1024] com.liferay.portal.struts.ActionException: java.lang.IllegalThreadStateException
com.liferay.portal.struts.ActionException: java.lang.IllegalThreadStateException
	at com.liferay.portal.events.EventsProcessor._process(EventsProcessor.java:155)
	at com.liferay.portal.events.EventsProcessor.process(EventsProcessor.java:76)
	at com.liferay.portal.servlet.MainServlet.destroyCompany(MainServlet.java:1016)
	at com.liferay.portal.servlet.MainServlet.destroy(MainServlet.java:985)
	at org.apache.catalina.core.StandardWrapper.unload(StandardWrapper.java:1331)
	at org.apache.catalina.core.StandardWrapper.stop(StandardWrapper.java:1666)
	at org.apache.catalina.core.ContainerBase.removeChild(ContainerBase.java:892)
	at org.apache.catalina.core.StandardContext.removeChild(StandardContext.java:3095)
	at org.apache.catalina.startup.ContextConfig.stop(ContextConfig.java:1082)
	at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:276)
	at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
	at org.apache.catalina.core.StandardContext.stop(StandardContext.java:4355)
	at org.apache.catalina.core.ContainerBase.removeChild(ContainerBase.java:892)
	at org.apache.catalina.startup.HostConfig.undeployApps(HostConfig.java:1164)
	at org.apache.catalina.startup.HostConfig.stop(HostConfig.java:1135)
	at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:312)
	at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
	at org.apache.catalina.core.ContainerBase.stop(ContainerBase.java:1054)
	at org.apache.catalina.core.ContainerBase.stop(ContainerBase.java:1066)
	at org.apache.catalina.core.StandardEngine.stop(StandardEngine.java:447)
	at org.apache.catalina.core.StandardService.stop(StandardService.java:512)
	at org.apache.catalina.core.StandardServer.stop(StandardServer.java:743)
	at org.apache.catalina.startup.Catalina.stop(Catalina.java:601)
	at org.apache.catalina.startup.Catalina.start(Catalina.java:576)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:294)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:432)
Caused by: java.lang.IllegalThreadStateException
	at java.lang.ThreadGroup.destroy(ThreadGroup.java:743)
	at com.liferay.portal.events.GlobalShutdownAction.run(GlobalShutdownAction.java:164)
	at com.liferay.portal.events.EventsProcessor._process(EventsProcessor.java:152)
	... 29 more


Third thing is some more warnings in logfile, related to hostname mappings:
02:13:06,205 WARN  [VirtualHostFilter:163] com.liferay.portal.NoSuchLayoutSetException: No LayoutSet exists with the key {companyId=1902, virtualHost=virtualybe}
02:13:26,324 WARN  [VirtualHostFilter:163] com.liferay.portal.NoSuchLayoutSetException: No LayoutSet exists with the key {companyId=1902, virtualHost=virtualybe}

I think it started after i've edited asp-hosts.properties to change companyId for hostname, which before was assigned to another companyId, but i am not sure about it, i will look at this more and will post again something will clear out.

So, for now this much, but really it is 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. IMO first thing to do it would be recheck twice about any possible issues, and don't go into advancing features to much, otherwise it can stretch till LEP.5...

P.S. [offtoppic] Since i need ASP style virtualhosting, and there are more ppl who needs that i think it would be very nice if together it would be included another bugfix about virtualhosting :http://support.liferay.com/browse/LEP-2532,. It is resolved already with patches for 4.2.x and latest 4.3 and i have been running LEP with this patch for month or so in my server, so i think it's not a bit trouble to include it in SVN, as it is quite trivial fix and is not affecting any other parts ...
16246, modified 19 Years ago. Junior Member Posts: 73 Join Date: 8/1/05 Recent Posts
Hi Andrius,

sorry about any trouble with properties load and the unused BUNDLE_NAME... the first try was just a proof-of concept (AKA "quick and dirty try" or QaDT) in order to test if that was an easy/hard functionality to have inside LEP. The thread problem would be related to the fact that this QaDT didn't use the "scheduler" features inside LEP, so the thread in charge of watching the mappings file -maybe- can be a little bit problematic. This would be addressed if, finally, this code gets into the main svn tree, by replacing that thread with an scheduler task.

Regarding the VirtualHostFilter, I think that's something related with the "virtual hosting through communities" that is not related -yet- with ASPHosting. I think that the right way (if you take a look at the wiki page for this project) would be to make ASPHosting (the "pure" ASP proposed by my with the first patch) absolutely compatible and synchronized with the "virtual hosting through communities", basically, allowing only virtual hosting communities under the set of domains managed by the company_id.

I think there's some movement around the Jira issue related to the "pure ASP" improvement request, so maybe we can see it inside some of the next releases! I hope so, since I'm also using it already in a production environment, and I think that's a functionality that would greatly improve and simplify the life of all of us using this, in some of its versions (replicated webapps, etc.)

Best,
Jose

---
triarium.com Liferay ASP hosting and services
16246, modified 19 Years ago. Junior Member Posts: 73 Join Date: 8/1/05 Recent Posts
Mika Koivisto:
Hi Jose!

Excellent work.

Is there a reason why it is in a properties file and not in database as the the virtual host mapping for communities? This would offer greater flexibility to be able to add new companies dynamically.


Properties file is used instead of DB because this was just (initially) a proof of concept. Actually it shouldn't be hard to move it to DB and to include some new tab in the admin (omniadmin) portlet to let omniadmin user manage this settings.

Despite the fact that data, currently, is stored in this properties file, this implementation allows the addition/removing of companies on-the-fly (just edit the properties file and comment out the line of the company you want to remove or add a new line with a companyId->domains mapping: the system scans this file periodically, each n seconds (configurable) and refreshes the settings, starting/stoping companyIds as needed)

Best,
Jose