[MAGNOLIA-233] single service deployment Created: 06/Dec/04  Updated: 11/Mar/05  Resolved: 11/Mar/05

Status: Closed
Project: Magnolia
Component/s: admininterface, core
Affects Version/s: 2.0 Final
Fix Version/s: 2.1 Final

Type: Improvement Priority: Major
Reporter: Sameer Charles Assignee: Sameer Charles
Resolution: Fixed Votes: 3
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

It should be possible to deploy multiple magnolia instances under one container service


Template:
Acceptance criteria:
Empty
Task DoD:
[ ]* Doc/release notes changes? Comment present?
[ ]* Downstream builds green?
[ ]* Solution information and context easily available?
[ ]* Tests
[ ]* FixVersion filled and not yet released
[ ]  Architecture Decision Record (ADR)
Date of First Response:

 Description   

So, what is to do if you want to deploy magnolia as a war without changing server.xml?

The point is the context of the web application. This means that every URL created by
Magnolia start must start with the correct context. For example all URL produced by the author instance should start with
/author and all URL produced by the public instance should start with /public

First you have to define the context as a prefix in the config section (this should not be a problem)

Then there are two possibilities:
1. Setting up a filter which checks the URLs and does respective rewriting (let's call it "link checking"). This would mean that Magnolia must parse every JSP page and do the rewriting. Of course we could check broken links here as well...
2. Whenever you create a URL make sure to use this prefix (admintemplates and custom templates/paragraphs).

In either ways the Magnolia team should support one of these.

Ralf



 Comments   
Comment by Sameer Charles [ 06/Dec/04 ]

that's exactly the point.

Then there are two possibilities:
1. Setting up a filter which checks the URLs and does respective rewriting (let's call it "link checking"). This would mean that Magnolia must parse every JSP page and do the rewriting. Of course we could check broken links here as well...

we can wrap response but that will badly effects the performance , since some servlet containers like weblogic would load the response in memory before
spooling it to the client.

2. Whenever you create a URL make sure to use this prefix (admintemplates and custom templates/paragraphs).

we should have some virtual prefix URI which we can always ignore while aggregating the content, and as you said presentation logic must take care
of rendering links including this prefix (eg. /author)

for war deployment I will create a build script but before that we need to figure out the best way to handle this URI mapping.

Comment by Ortwin Glueck [ 06/Dec/04 ]

A servlet can determine the context string with ServletContext#getServletContextName().

But ideally a servlet should not produce any absolute URLs at all but only relative ones.

Comment by Sameer Charles [ 09/Feb/05 ]

Fabrizio:

I saw in your comments on svn that you already did something in this regard? could you please explain me what exactly you did?
I would like to start work on this, such that magnolia could be deployed in sub contexts.

Comment by Fabrizio Giustina [ 09/Feb/05 ]

Yes, I started working on it and I think it will not be so hard to make magnolia fully work without to be bound to the root context.

This is what need to be done and what I did till now:

  • Fix entryservlet and resourceDispatcher to ignore context root in request (remove request.getContextPath() from request.getRequestURI()) DONE
  • Fix paths in jsp or gui controls to always prepend context path for linked resources. Done for linked css and js file adding a context path parameter in the Sources contructor, started to add context path to images and links in jsp pages (adminCentral.jsp and extractTree.jsp should be ok, other pages still need to be fixed)
  • Check and fix js functions: adminCentral.js mgnlAdminCentralSwitchExtractTree only works properly if you gives the url (with the prependended context path) as a parameter. The default url (without the context path) will never work. I actually fixed calls from admincentral adding the "href" parameter, but a more complete solution will be to define a js variable wich can hold the current context path and use it for each request. Without this for example custom buttons in the admin interface will not work when changing context (since you have to hardcode the url). This is probably the hardest point.

With this changes magnolia is able to ork in subcontext but it still requires the mapping of the docroot/admindocroot directories in server.xml:
<Host name="localhost"appBase="webapps" ...>
<Context path="/magnolia/docroot" docBase="magnolia/docroot" />
<Context path="/magnolia/admindocroot" docBase="magnolia/admindocroot" />
</Host>
If you don't define these 2 context magnolia will intercept all request, also for static content.
The last step will then be find a way to not to intercept requests directed to the docroot and admindocroot paths. After this, you could drop magnolia war in tomcat webapp folder and see it working!

Comment by Fabrizio Giustina [ 09/Feb/05 ]

well, another important step:

  • cache and internal links: internal links need to be fixed with a prepended context root (easy), but since the same web application could be accessed using a context path (eg. direct access from tomcat) or with a root context (eg tomcat linked from apache) cache should save different entries for calls coming with different contexts.
Comment by Sameer Charles [ 09/Feb/05 ]
  • The last step will then be find a way to not to intercept requests directed to the docroot and admindocroot paths. After this, you could drop magnolia war in tomcat webapp folder and see it working!

why dont we simply add a spool servlet inside magnolia context which will take over all requests to
$CONTEXT$/docroot and $CONTEXT$/admindocroot ?

  • cache and internal links: internal links need to be fixed with a prepended context root (easy), but since the same web application could be accessed using a context path (eg. direct access from tomcat) or with a root context (eg tomcat linked from apache) cache should save different entries for calls coming with different contexts.

For cache handler its not a big deal, it could easily resolve path with or without context. - ll do that

Comment by Sameer Charles [ 10/Feb/05 ]

(to switch off security on static resources add these to config/server/SecureURI deny list)

Comment by Fabrizio Giustina [ 10/Feb/05 ]

the spool servlet works perfectly for me.

I fixed more gui elements, jsp, js, and page templates. Now magnolia WORKS when dropped in tomcat without any modification to server.xml, but there will probably be still some glitches or problems...

the getContextPath() thing needed to be added in lots of places and in gui controls you actually can't know if the request has been set or not (all the controls extends ControlSuper which has a getRequest, and there are different contructor, with or without request). Another problem is that NPE are generally catched and ignored without any log so it's also difficult to see if an error has occurred (if something is missing in the page, probably it has).

Anyway, it mostly works for me: we need to review and test everything accurately (and add log when an exception is swallowed)... the bigger part of the work is done

Comment by Andy [ 24/Feb/05 ]

Hope this formats ok? Here is an example of how I have modified ALL of the config classes to make them context based. Once all of the config classes have been modified in this way it is pretty easy to follow through the compile process and make the additional changes.

public class Listener {

private static Logger log = Logger.getLogger(Listener.class);
private static final String CONFIG_PAGE = "server";

/**
*Map for context based access
*/
private static HashMap cachedContextContent = new HashMap();

/**

  • constructor
    */
    private Listener(){}

/**
*Provides a cachedContent HashMap per ServletContext
*/
private static HashMap cachedContent(ServletContext context){
if(!cachedContextContent.containsKey(context.getServletContextName()))

{ cachedContextContent.put(context.getServletContextName(), new HashMap()); }

return ((HashMap)cachedContextContent.get(context.getServletContextName()));
}

/**

  • <p>reads listener config from the config repository and caches its content
  • in to the hash table</p>
    *
    */
    public static void init(ServletContext context)
    Unknown macro: { try { log.info("Config : loading Listener info for context: " + context.getServletContextName()); Content startPage = ContentRepository.getHierarchyManager(context ,ContentRepository.CONFIG).getPage(CONFIG_PAGE); //When I access my cache then it is always the cache for my ServletContext cachedContent(context).clear(); cacheContent(context,startPage.getContentNode("IPConfig").getChildren().iterator()); log.info("Config : Listener info loaded for context: " + context.getServletContextName()); } catch (RepositoryException re) { log.error("Config : Failed to load Listener info for context: " + context.getServletContextName()); log.error(re.getMessage(), re); } }

public static void reload(ServletContext context)

{ log.info("Config : re-loading Listener info for context: " + context.getServletContextName()); init(context); }

/**

  • <p>Cache listener content from the config repository (Context based)</p>
    */
    private static void cacheContent(ServletContext context, Iterator ipList) {
    while(ipList.hasNext()) {

Content c = (Content) ipList.next();

try {
HashMap types = new HashMap();
cachedContent(context).put((context.getServletContextName() + "." + c.getNodeData("IP").getString()),types);

Iterator it = c.getContentNode("Access").getChildren().iterator();
while (it.hasNext())

{ Content type = (Content) it.next(); types.put(type.getNodeData("Method").getString().toLowerCase(),""); }

} catch (RepositoryException re) {}
}

ipList = null;
}

/**

  • <p>get access info of the requested IP (Context based)
  • </p>
  • @param key IP tp be checked
  • @return HashMap containing Access info
  • @throws Exception
    */
    public static HashMap getInfo(ServletContext context, String key) throws Exception { return (HashMap) cachedContent(context).get((context.getServletContextName() + "." + key)); }

}

Comment by Fabrizio Giustina [ 24/Feb/05 ]

Andy, in the current svn trunk all the needed classes have already been modified adding the servletContext where appropriate.

There is still some work to do on the front end part, but IHMO the java side is already ok. The problem actually is to fix and test all the javascript functions to make them context based (XmlHttpRequests are fixed, some few other js functions which load urls are not yet working).
BTW if you try compiling magnolia from trunk you absolutely will be able to run it simply dropping the war into tomcat (and adding the repository content which is not in svn) with only a few glitches.

Comment by Fabrizio Giustina [ 11/Mar/05 ]

fixed in svn for 2.1.
activation is fixed (adding contextPath to senderUrl) and now everything seems to work fine. Javascript function have been modified and js files are now parsed by the server, so it's easy to add the contextPath where needed.
Test it!

Generated at Mon Feb 12 03:15:24 CET 2024 using Jira 9.4.2#940002-sha1:46d1a51de284217efdcb32434eab47a99af2938b.