You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@jackrabbit.apache.org by Jukka Zitting <ju...@gmail.com> on 2007/06/04 00:13:46 UTC

Re: Proposal for managing JCR resources in webapps

Hi,

I've now implemented (see JCR-956 and the many related commits) a set
of servlets and other classes based on the ideas discussed earlier in
this thread.

The new code and fairly complete javadocs can be found in the
following packages:

    jackrabbit-jcr-commons:
        org.apache.jackrabbit.commons.repository
        org.apache.jackrabbit.commons.servlet
    jackrabbit-jcr-rmi:
        org.apache.jackrabbit.rmi.repository
        org.apache.jackrabbit.rmi.servlet
    jackrabbit-core:
        org.apache.jackrabbit.core.servlet

To give a short overview of what's possible with these new classes,
here's how to instantiate a Jackrabbit repository with default
configuration and make it available in the application scope:

    <servlet>
      <servlet-name>Repository</servlet-name>
      <servlet-class>
        org.apache.jackrabbit.core.servlet.JackrabbitRepositoryServlet
      </servlet-class>
      <init-param>
        <param-name>repository.home</param-name>
        <param-value>/path/to/repository/home/directory</param-value>
      </init-param>
      <load-on-startup>1</load-on-startup>
    </servlet>

The org.apache.jackrabbit.commons.servlet.ServletRepository class can
be used to transparently access this repository (or any other
repository in application scope):

    public class MyServlet extends HttpServlet {
        private final Repository repository = new ServletRepository(this);
    }

The ServletRepository class will automatically look up the actual
repository instance on demand from the servlet context and proxy any
method calls to it.

As a bonus feature, the repository servlet can be mapped to the URL
space to get easy access to repository descriptors:

    <servlet-mapping>
      <servlet-name>Repository</servlet-name>
      <url-pattern>/repository/*</url-pattern>
    </servlet-mapping>

For example the name of the repository vendor is then available as
text/plain via HTTP GET at
http://host:port/context/repository/jcr.repository.vendor.

The instantiated repository can be made remotely accessible via RMI
with the following configuration:

    <servlet>
      <servlet-name>RemoteRepository</servlet-name>
      <servlet-class>
        org.apache.jackrabbit.rmi.servlet.RemoteBindingServlet
      </servlet-class>
      <load-on-startup>2</load-on-startup>
    </servlet>

    <servlet-mapping>
      <servlet-name>RemoteRepository</servlet-name>
      <url-pattern>/remote</url-pattern>
    </servlet-mapping>

The repository can then be accessed from a remote client using the
org.apache.jackrabbit.rmi.repository.URLRemoteRepository class:

    Repository repository = new
URLRemoteRepository("http://host:port/context/remote");

Replacing the RemoteBindingServlet class with RMIRemoteBindingServlet
or JNDIRemoteBindingServlet in the servlet configuration makes the
remote repository reference available also in an RMI registry or a
JNDI directory. Multiple such servlets can be configured in parallel
to make the remote reference available in multiple locations.

All the above options work just as well also with a non-local
repository instance. The JackrabbitRepositoryServlet configuration at
the beginning can be replaced for example with JNDIRepositoryServlet
or ContextRepositoryServlet from org.apache.jackrabbit.commons.servlet
to load the repository from JNDI or from another web application. Even
remote repositories can be used with servlets from
org.apache.jackrabbit.rmi.servlet.

The default is to have the repository in the "javax.jcr.Repository"
servlet context attribute, but the attribute name can be configured in
each of the mentioned servlets for example to allow the use of
multiple different repositories in a single web application.

PS. I haven't yet tried to port jackrabbit-webapp to use these new
servlets and classes as I'm not sure how they could best made to work
with the dynamic configuration mechanism in use there.

BR,

Jukka Zitting

Re: Proposal for managing JCR resources in webapps

Posted by Felix Meschberger <Fe...@day.com>.
Hi Jukka,

Thanks alot.

Regards
Felix

On 6/4/07, Jukka Zitting <ju...@gmail.com> wrote:
>
> Hi,
>
> On 6/4/07, Jukka Zitting <ju...@gmail.com> wrote:
> > Makes sense. I guess we could make the jackrabbit-jcr-rmi and
> > jackrabbit-core dependencies of the potential jackrabbit-servlet
> > component optional so a client would need to explicitly add those
> > dependencies if it wants to use those servlets.
>
> As of revision 544209 there is now a new component called
> jackrabbit-jcr-servlet that contains the new servlet classes. It has
> jackrabbit-jcr-rmi and jackrabbit-core as optional dependencies to
> avoid inflicting them to unsuspecting clients.
>
> The component is already top-level since I definitely want to include
> this in Jackrabbit 1.4.
>
> BR,
>
> Jukka Zitting
>

Re: Proposal for managing JCR resources in webapps

Posted by Jukka Zitting <ju...@gmail.com>.
Hi,

On 6/4/07, Jukka Zitting <ju...@gmail.com> wrote:
> Makes sense. I guess we could make the jackrabbit-jcr-rmi and
> jackrabbit-core dependencies of the potential jackrabbit-servlet
> component optional so a client would need to explicitly add those
> dependencies if it wants to use those servlets.

As of revision 544209 there is now a new component called
jackrabbit-jcr-servlet that contains the new servlet classes. It has
jackrabbit-jcr-rmi and jackrabbit-core as optional dependencies to
avoid inflicting them to unsuspecting clients.

The component is already top-level since I definitely want to include
this in Jackrabbit 1.4.

BR,

Jukka Zitting

Re: Proposal for managing JCR resources in webapps

Posted by Jukka Zitting <ju...@gmail.com>.
Hi,

On 6/4/07, Felix Meschberger <Fe...@day.com> wrote:
> On 6/4/07, Jukka Zitting <ju...@gmail.com> wrote:
> >     jackrabbit-jcr-servlet (depends on jackrabbit-jcr-commons)
> >     jackrabbit-jcr-rmi-servlet (depends on jackrabbit-jcr-rmi,
> > jackrabbit-jcr-servlet)
> >     jackrabbit-core-servlet (depends on jackrabbit-core, jackrabbit-jcr-servlet)
>
> No, I would say that there is only one single component for the
> servlet integration case. Of course you would get dependencies on the
> jcr-commons (you have this any probably) on rmi (true, but i you
> require rmi, you need rmi) and core (worst actually, but if you create
> a repository, you need this anyway).
>
> If we start adding container support to the different components,
> there is no apparent stop - or would you add support for Spring, Pico
> Container, Nano Container, whatever-container to each of the
> components ?

Makes sense. I guess we could make the jackrabbit-jcr-rmi and
jackrabbit-core dependencies of the potential jackrabbit-servlet
component optional so a client would need to explicitly add those
dependencies if it wants to use those servlets.

> BTW: rmi depends on Xerces. Just to support XML import, this is rather
> heavy, isn't it ?

Agreed. Time for an improvement issue?

BR,

Jukka Zitting

Re: Proposal for managing JCR resources in webapps

Posted by Felix Meschberger <Fe...@day.com>.
Hi,

On 6/4/07, Jukka Zitting <ju...@gmail.com> wrote:
> I considered that but then we'd need explicit invalidation of the
> memorized repository reference. I want to be able to for example
> restart the repository accessed through JNDI or across servlet
> contexts without having to redeploy also all the applications that use
> the repository. Re-acquiring the reference for each method call
> achieves this in a clean and simple way.

ok

>
>     jackrabbit-jcr-servlet (depends on jackrabbit-jcr-commons)
>     jackrabbit-jcr-rmi-servlet (depends on jackrabbit-jcr-rmi,
> jackrabbit-jcr-servlet)
>     jackrabbit-core-servlet (depends on jackrabbit-core, jackrabbit-jcr-servlet)
>

No, I would say that there is only one single component for the
servlet integration case. Of course you would get dependencies on the
jcr-commons (you have this any probably) on rmi (true, but i you
require rmi, you need rmi) and core (worst actually, but if you create
a repository, you need this anyway).

If we start adding container support to the different components,
there is no apparent stop - or would you add support for Spring, Pico
Container, Nano Container, whatever-container to each of the
components ?

Regards
Felix

BTW: rmi depends on Xerces. Just to support XML import, this is rather
heavy, isn't it ?

Re: Proposal for managing JCR resources in webapps

Posted by Jukka Zitting <ju...@gmail.com>.
Hi,

On 6/4/07, Felix Meschberger <Fe...@day.com> wrote:
>    - The org.apache.jackrabbit.commons.repository.ProxyRepository class
>    does not only access the repository lazily but "re-acquires" the repository
>    on each call. This seems somewhat too expensive. I suggest to add an
>    accessor method, which accesses the repository realy lazily.

I considered that but then we'd need explicit invalidation of the
memorized repository reference. I want to be able to for example
restart the repository accessed through JNDI or across servlet
contexts without having to redeploy also all the applications that use
the repository. Re-acquiring the reference for each method call
achieves this in a clean and simple way.

Most often the repository is also used just for a login() call, which
in any case is more expensive than the typical repository lookup. The
only time I think the lookup time will dominate access time is when a
client reads the repository descriptors. This would typically be an
administration operation so I don't think optimizing that is very
important.

Typically the repository lookup is also very fast for example when
using local JNDI or a servlet context. The only case where the lookup
would be more expensive is when accessing a remote repository, but
such cases would typically not be performance-critical in any case and
even there the typical performance hit would be a few extra
milliseconds per login() call.

>    - I tend to not like the inclusion of Serlvet API specific methods in
>    the commons and rmi libraries. IMHO using JCR in a Servlet Context is a very
>    valid and probably most often used use case but it is not the sole and
>    primary and most important use case. So adding dependencies to the Servlet
>    API to these two libraries seems unfit. Rather I suggest to have a separate
>    library supporting the important Servlet Context use case which combines the
>    servlet support packages from the commons and rmi libraries.

We already have quite a few components to manage, so I'd prefer to
avoid creating a yet another component. The servlet-api dependency
scope is provided, so an application that doesn't use classes in the
o.a.j.*.servlet packages would not be affected by the dependency.

I could of course create such an extra component, but then it becomes
a question of whether we should have separate components for the
generic classes and ones specific to jackrabbit-jcr-rmi or
jackrabbit-core or if we should just have a single jackrabbit-servlet
component that depends on all these pieces. Following the former
option (that doesn't impose extra dependencies to clients) would give
us (at least):

    jackrabbit-jcr-servlet (depends on jackrabbit-jcr-commons)
    jackrabbit-jcr-rmi-servlet (depends on jackrabbit-jcr-rmi,
jackrabbit-jcr-servlet)
    jackrabbit-core-servlet (depends on jackrabbit-core, jackrabbit-jcr-servlet)

This simply duplicates the existing jcr-commons/jcr-rmi/core triple,
so in my opinion we would be better of just accepting the (provided)
servlet-api dependency in existing components.

BR,

Jukka Zitting

Re: Proposal for managing JCR resources in webapps

Posted by Felix Meschberger <Fe...@day.com>.
Hi Jukka,

First of all, thanks for this rework. It is a great thing and cleanly
abstracts many aspects of providing and accessing repositories.

I have just two small notes on this:

   - The org.apache.jackrabbit.commons.repository.ProxyRepository class
   does not only access the repository lazily but "re-acquires" the repository
   on each call. This seems somewhat too expensive. I suggest to add an
   accessor method, which accesses the repository realy lazily.
   - I tend to not like the inclusion of Serlvet API specific methods in
   the commons and rmi libraries. IMHO using JCR in a Servlet Context is a very
   valid and probably most often used use case but it is not the sole and
   primary and most important use case. So adding dependencies to the Servlet
   API to these two libraries seems unfit. Rather I suggest to have a separate
   library supporting the important Servlet Context use case which combines the
   servlet support packages from the commons and rmi libraries.

Again, well done and thanks.

Regards
Felix

On 6/4/07, Jukka Zitting <ju...@gmail.com> wrote:
>
> Hi,
>
> I've now implemented (see JCR-956 and the many related commits) a set
> of servlets and other classes based on the ideas discussed earlier in
> this thread.
>
> The new code and fairly complete javadocs can be found in the
> following packages:
>
>     jackrabbit-jcr-commons:
>         org.apache.jackrabbit.commons.repository
>         org.apache.jackrabbit.commons.servlet
>     jackrabbit-jcr-rmi:
>         org.apache.jackrabbit.rmi.repository
>         org.apache.jackrabbit.rmi.servlet
>     jackrabbit-core:
>         org.apache.jackrabbit.core.servlet
>
> To give a short overview of what's possible with these new classes,
> here's how to instantiate a Jackrabbit repository with default
> configuration and make it available in the application scope:
>
>     <servlet>
>       <servlet-name>Repository</servlet-name>
>       <servlet-class>
>         org.apache.jackrabbit.core.servlet.JackrabbitRepositoryServlet
>       </servlet-class>
>       <init-param>
>         <param-name>repository.home</param-name>
>         <param-value>/path/to/repository/home/directory</param-value>
>       </init-param>
>       <load-on-startup>1</load-on-startup>
>     </servlet>
>
> The org.apache.jackrabbit.commons.servlet.ServletRepository class can
> be used to transparently access this repository (or any other
> repository in application scope):
>
>     public class MyServlet extends HttpServlet {
>         private final Repository repository = new ServletRepository(this);
>     }
>
> The ServletRepository class will automatically look up the actual
> repository instance on demand from the servlet context and proxy any
> method calls to it.
>
> As a bonus feature, the repository servlet can be mapped to the URL
> space to get easy access to repository descriptors:
>
>     <servlet-mapping>
>       <servlet-name>Repository</servlet-name>
>       <url-pattern>/repository/*</url-pattern>
>     </servlet-mapping>
>
> For example the name of the repository vendor is then available as
> text/plain via HTTP GET at
> http://host:port/context/repository/jcr.repository.vendor.
>
> The instantiated repository can be made remotely accessible via RMI
> with the following configuration:
>
>     <servlet>
>       <servlet-name>RemoteRepository</servlet-name>
>       <servlet-class>
>         org.apache.jackrabbit.rmi.servlet.RemoteBindingServlet
>       </servlet-class>
>       <load-on-startup>2</load-on-startup>
>     </servlet>
>
>     <servlet-mapping>
>       <servlet-name>RemoteRepository</servlet-name>
>       <url-pattern>/remote</url-pattern>
>     </servlet-mapping>
>
> The repository can then be accessed from a remote client using the
> org.apache.jackrabbit.rmi.repository.URLRemoteRepository class:
>
>     Repository repository = new
> URLRemoteRepository("http://host:port/context/remote");
>
> Replacing the RemoteBindingServlet class with RMIRemoteBindingServlet
> or JNDIRemoteBindingServlet in the servlet configuration makes the
> remote repository reference available also in an RMI registry or a
> JNDI directory. Multiple such servlets can be configured in parallel
> to make the remote reference available in multiple locations.
>
> All the above options work just as well also with a non-local
> repository instance. The JackrabbitRepositoryServlet configuration at
> the beginning can be replaced for example with JNDIRepositoryServlet
> or ContextRepositoryServlet from org.apache.jackrabbit.commons.servlet
> to load the repository from JNDI or from another web application. Even
> remote repositories can be used with servlets from
> org.apache.jackrabbit.rmi.servlet.
>
> The default is to have the repository in the "javax.jcr.Repository"
> servlet context attribute, but the attribute name can be configured in
> each of the mentioned servlets for example to allow the use of
> multiple different repositories in a single web application.
>
> PS. I haven't yet tried to port jackrabbit-webapp to use these new
> servlets and classes as I'm not sure how they could best made to work
> with the dynamic configuration mechanism in use there.
>
> BR,
>
> Jukka Zitting
>

Re: Proposal for managing JCR resources in webapps

Posted by Jukka Zitting <ju...@gmail.com>.
Hi,

On 6/4/07, Marcel Reutegger <ma...@gmx.net> wrote:
> Jukka Zitting wrote:
> > As a bonus feature, the repository servlet can be mapped to the URL
> > space to get easy access to repository descriptors:
> >
> >    <servlet-mapping>
> >      <servlet-name>Repository</servlet-name>
> >      <url-pattern>/repository/*</url-pattern>
> >    </servlet-mapping>
> >
> > For example the name of the repository vendor is then available as
> > text/plain via HTTP GET at
> > http://host:port/context/repository/jcr.repository.vendor.
>
> that's a very nice feature, but please note that the jackrabbit-webapp per
> default maps /repository to the webdav servlet. therefore we should rather use a
> different path as an example, just to avoid confusion. how about
> /repository-descriptor ?

Good point, I'll keep it in mind when writing more documentation on
these servlets.

BR,

Jukka Zitting

Re: Proposal for managing JCR resources in webapps

Posted by Marcel Reutegger <ma...@gmx.net>.
Jukka Zitting wrote:
> As a bonus feature, the repository servlet can be mapped to the URL
> space to get easy access to repository descriptors:
> 
>    <servlet-mapping>
>      <servlet-name>Repository</servlet-name>
>      <url-pattern>/repository/*</url-pattern>
>    </servlet-mapping>
> 
> For example the name of the repository vendor is then available as
> text/plain via HTTP GET at
> http://host:port/context/repository/jcr.repository.vendor.

that's a very nice feature, but please note that the jackrabbit-webapp per 
default maps /repository to the webdav servlet. therefore we should rather use a 
different path as an example, just to avoid confusion. how about 
/repository-descriptor ?

regards
  marcel