[opencms-dev] access to CmsObject - Spring and OpenCms

Jonathan Woods jonathan.woods at scintillance.com
Fri Aug 7 08:29:53 CEST 2009


(Achim, Alexander and the Alkacon crew: would you consider adding 4(b)
below?)

Maybe Christian meant OpenCms.  Anyway, there's effectively new instance of
CmsObject for each request, not least because CmsObject holds a reference to
CmsRequestContext.

I managed to make OpenCms 'properly Spring MVC' in the way I think you're
seeking.  By that I mean making the OpenCms webapp itself a SpringMVC webap,
rather than merely using OpenCms as a heavyweight view resolver or as an
external webapp to dispatch to manually.  I've been meaning to publish my
working, but there's never time!  Anyway, here are the rough steps I took:

1.  Include the Spring dispatcher servlet in web.xml, and have it start
before OpenCms's servlets.

2.  Also include Spring's ContextLoaderListener as usual.  I use a subclass,
ForgivingContextLoaderListener, which at least lets OpenCms start up even if
there's a Spring error, so that editing/administration can go on as normal.

3.  Configure a servlet request interceptor which makes available in request
state a suitably configured instance of CmsObject... more below.

4.  (a) That CmsObject instance is obtained from a slightly modified version
of org.opencms.main.OpenCmsCore.  Yes, I know - I was dismayed too at having
to stoop to this level!  The problem is that although you can follow the
long route through the source code to find out how CmsObject is initialised
from the HttpServletRequest object, there's no way (afaict) to repeat this
logic outside the usual context without putting code in that class.
Fortunately, I've not had to rebuild OpenCms from scratch: I can persuade my
servlet container (Tomcat) to load a modified version of the class before it
loads OpenCms's.

(b) Here's the additional method.  I wonder if Alkacon would consider adding
this to the API?  If not here (because it's OpenCmsCore, and a method like
this needs to be accessible to third-party code) then somewhere else.  It
doesn't do anything that isn't already possible - rather, it does less than
is already possible: other externally accessible methods for obtaining
CmsObject from the request also unfortunately end up dispatching to login
handlers - hence the naming of this method, because it doesn't have that
side effect.  I've spent a bit of time thinking about security, and I can't
see a problem with exposing something like this, even in situations where
you can't trust users of OpenCms with the ability to create and run code
(e.g. via JSPs).  It doesn't elevate privileges, afaict, and doesn't provide
CmsObjects to anyone who can't already get them.

	public static CmsObject
getCmsObjectWithoutSideEffects(HttpServletRequest request) throws
CmsException {

		OpenCmsCore openCmsCore = getInstance();
		
		// First try to retrieve the OpenCms user context from an
existing session.  The invocation of an
		// OpenCmsCore method is the reason we need _this_ method to
be in the same class.

		CmsObject cms =
openCmsCore.initCmsObjectFromSession(request);

		if (cms != null) {
			return cms;
		}

		// If nothing's available from the session, use (what looks
like a standard) OpenCms way of deriving
		// CmsObject from the request alone.

		CmsSite site =
openCmsCore.getSiteManager().matchRequest(request);

		return openCmsCore.initCmsObject(request,
openCmsCore.getSecurityManager().readUser(null,
OpenCms.getDefaultUsers().getUserGuest()), site.getSiteRoot(),
CmsProject.ONLINE_PROJECT_ID, "");
	}

5.  And now it's possible to reach the Spring-OpenCms Holy Grail: to perform
arbitrarily complex stuff in the usual controller/service/dao pattern and
set up state for any kind of view technology as well as for OpenCms JSPs.
And the rest of Spring benefits follow readily - e.g. ACEGI security, other
view technologies, easier unit testing.

6.  As an aside: I have a Spring HandlerMapping called
ResourceTypeHandlerMapping.  For a request path which you choose to map to a
VFS path, it determines the concrete handler based on the VFS resource type.
This matches the pattern of traditional OpenCms development, though of
course using SpringMVC means you can engineer controllers such that a
request can end up rendering content from arbitary VFS resources (or none).

Jon

> -----Original Message-----
> From: opencms-dev-bounces at opencms.org 
> [mailto:opencms-dev-bounces at opencms.org] On Behalf Of mvarshavsky
> Sent: 07 August 2009 01:34
> To: opencms-dev at opencms.org
> Subject: Re: [opencms-dev] access to CmsObject
> 
> 
> 
> 
> Christian Steinert wrote:
> > 
> > The CmsObject should be a singleton within any given web 
> application. 
> > There are factory methods to retrieve that instance, but they only 
> > work from within the web app.
> > 
> 
> 
> Okay - and, again, apologizing for my ignorance here - then 
> what's the talk about 
> OpenCms.initCmsObject(OpenCms.getDefaultUsers().getUserGuest()
> ) vs the logged in user. That gave me an impression that it 
> would vary depending on the user?
> --
> View this message in context: 
> http://www.nabble.com/access-to-CmsObject-tp21896856p24856931.html
> Sent from the OpenCMS - Dev mailing list archive at Nabble.com.
> 
> 
> _______________________________________________
> This mail is sent to you from the opencms-dev mailing list
> To change your list options, or to unsubscribe from the list, 
> please visit
> http://lists.opencms.org/mailman/listinfo/opencms-dev




More information about the opencms-dev mailing list