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/02/09 17:12:17 UTC

Layering the Jackrabbit JCR interface classes

Hi,

Jackrabbit currently implements the JCR interfaces directly in the
various Impl classes that directly access the underlying repository
state. This approach has a few drawbacks:

    a) The Impl classes are huge, partly because the JCR interfaces
       typically declare such a large number of methods. For example:
       NodeImpl = 4.2kLOC, SessionImpl = 1.4kLOC, PropertyImpl = 1.2kLOC.

    b) Related to the above, the Impl classes have a large number of
       separate responsibilities, but as of now the fixed nature of the
       JCR interfaces prevent easy refactoring of those responsibilities
       to separate classes.

    c) Many Impl classes expose extra public or protected methods in
       addition to the ones declared in the JCR interfaces. This introduces
       potential security issues, especially when in some cases exposing
       some internal features to other internal classes would in fact be
       beneficial (for example access to the system session).

    d) The JCR interfaces contain many utility methods that can be
       implemented in terms of other JCR methods. Such default methods
       could easily be shared across JCR implementations but the nature
       of the current Impl classes prevents such sharing.

    e) Name parsing and formatting is normally only performed just when
       entering or leaving a JCR method. This mapping activity is currently
       duplicated in almost all method implementations.

I would like to suggest that we introduce a new layer just beneath the
JCR API for getting rid of or reducing the above drawbacks. This layer
would consist of the following three parts:

    1) Set of abstract AbstractSession, AbstractItem, etc. classes that
       implement as much of the respective JCR interfaces using nothing
       else but calls to other JCR methods. These would be just like the
       AbstractMap, etc. classes in java.util.

    2) Set of QSession, QItem, etc. (or with some better naming) interfaces
       that declare QName and Path versions of those JCR methods that can't
       reasonably be implemented by the above abstract classess. Potentially
       we could also break strict one-to-one correspondence with the JCR
       interfaces to allow for better separation of concerns.

    3) Set of adapter (or facade) classes that extend the above abstract
       classes and implement the remaining methods using name mapping and
       implementations of the above interfaces. These classes could also
       take care of backreferences like Session.getRepository() and
       Item.getSession().

All these parts could be implemented within jackrabbit-jcr-commons so
that they can be reused in other JCR implementations, for example in
the client part of the SPI project.

The current Impl classes in jackrabbit-core would be refactored to
implement the above interfaces instead of the standard JCR interfaces.

What do you think? At least the first part of the proposal should be
easy to implement incrementally without destabilizing anything. The
granularity of implementing the other parts is a bit bigger, but could
still be performed just one interface at a time.

BR,

Jukka Zitting

Re: Layering the Jackrabbit JCR interface classes

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

On 2/9/07, Stefan Guggisberg <st...@gmail.com> wrote:
> however, we should IMO be careful not to blindly sacrifice performance
> for cleaner code. a move operation could e.g. be modeled as a copy&delete,
> this might make sense from a design perspective, but not performance wise.

Agreed. The move vs copy&delete case is quite extreme, but even things
like implementing Item.getAncestor(), Item.getPath(), or
Item.getDepth() in terms of Item.getParent() are potential performance
issues. There is however no stopping jackrabbit-core from extending
the adapters and interfaces from the proposed generic solution to
provide implementation-specific improvements for cases where
performance gains are available. Thus I don't think the proposed
solution introduces any design-induced performance issues that
couldn't be easily avoided.

As a general guideline I'd set the maximum allowed performance hit of
the proposed layering to an extra one or two indirect calls per
implemented method. If the performance hit seems worse, then we keep
the current structure.

BR,

Jukka Zitting

Re: Layering the Jackrabbit JCR interface classes

Posted by Stefan Guggisberg <st...@gmail.com>.
On 2/9/07, Jukka Zitting <ju...@gmail.com> wrote:
> Hi,
>
> Jackrabbit currently implements the JCR interfaces directly in the
> various Impl classes that directly access the underlying repository
> state. This approach has a few drawbacks:
>
>     a) The Impl classes are huge, partly because the JCR interfaces
>        typically declare such a large number of methods. For example:
>        NodeImpl = 4.2kLOC, SessionImpl = 1.4kLOC, PropertyImpl = 1.2kLOC.
>
>     b) Related to the above, the Impl classes have a large number of
>        separate responsibilities, but as of now the fixed nature of the
>        JCR interfaces prevent easy refactoring of those responsibilities
>        to separate classes.
>
>     c) Many Impl classes expose extra public or protected methods in
>        addition to the ones declared in the JCR interfaces. This introduces
>        potential security issues, especially when in some cases exposing
>        some internal features to other internal classes would in fact be
>        beneficial (for example access to the system session).
>
>     d) The JCR interfaces contain many utility methods that can be
>        implemented in terms of other JCR methods. Such default methods
>        could easily be shared across JCR implementations but the nature
>        of the current Impl classes prevents such sharing.
>
>     e) Name parsing and formatting is normally only performed just when
>        entering or leaving a JCR method. This mapping activity is currently
>        duplicated in almost all method implementations.
>
> I would like to suggest that we introduce a new layer just beneath the
> JCR API for getting rid of or reducing the above drawbacks. This layer
> would consist of the following three parts:
>
>     1) Set of abstract AbstractSession, AbstractItem, etc. classes that
>        implement as much of the respective JCR interfaces using nothing
>        else but calls to other JCR methods. These would be just like the
>        AbstractMap, etc. classes in java.util.
>
>     2) Set of QSession, QItem, etc. (or with some better naming) interfaces
>        that declare QName and Path versions of those JCR methods that can't
>        reasonably be implemented by the above abstract classess. Potentially
>        we could also break strict one-to-one correspondence with the JCR
>        interfaces to allow for better separation of concerns.
>
>     3) Set of adapter (or facade) classes that extend the above abstract
>        classes and implement the remaining methods using name mapping and
>        implementations of the above interfaces. These classes could also
>        take care of backreferences like Session.getRepository() and
>        Item.getSession().
>
> All these parts could be implemented within jackrabbit-jcr-commons so
> that they can be reused in other JCR implementations, for example in
> the client part of the SPI project.
>
> The current Impl classes in jackrabbit-core would be refactored to
> implement the above interfaces instead of the standard JCR interfaces.
>
> What do you think? At least the first part of the proposal should be
> easy to implement incrementally without destabilizing anything. The
> granularity of implementing the other parts is a bit bigger, but could
> still be performed just one interface at a time.

sounds good, +1 in general.

however, we should IMO be careful not to blindly sacrifice performance
for cleaner code. a move operation could e.g. be modeled as a copy&delete,
this might make sense from a design perspective, but not performance wise.

cheers
stefan

>
> BR,
>
> Jukka Zitting
>

Re: Layering the Jackrabbit JCR interface classes

Posted by Tobias Bocanegra <to...@day.com>.
sound good; but i would have the q-inetrfaces in jackrabit-api rather
than in jcr-commons.

regards toby

On 2/9/07, Jukka Zitting <ju...@gmail.com> wrote:
> Hi,
>
> Jackrabbit currently implements the JCR interfaces directly in the
> various Impl classes that directly access the underlying repository
> state. This approach has a few drawbacks:
>
>     a) The Impl classes are huge, partly because the JCR interfaces
>        typically declare such a large number of methods. For example:
>        NodeImpl = 4.2kLOC, SessionImpl = 1.4kLOC, PropertyImpl = 1.2kLOC.
>
>     b) Related to the above, the Impl classes have a large number of
>        separate responsibilities, but as of now the fixed nature of the
>        JCR interfaces prevent easy refactoring of those responsibilities
>        to separate classes.
>
>     c) Many Impl classes expose extra public or protected methods in
>        addition to the ones declared in the JCR interfaces. This introduces
>        potential security issues, especially when in some cases exposing
>        some internal features to other internal classes would in fact be
>        beneficial (for example access to the system session).
>
>     d) The JCR interfaces contain many utility methods that can be
>        implemented in terms of other JCR methods. Such default methods
>        could easily be shared across JCR implementations but the nature
>        of the current Impl classes prevents such sharing.
>
>     e) Name parsing and formatting is normally only performed just when
>        entering or leaving a JCR method. This mapping activity is currently
>        duplicated in almost all method implementations.
>
> I would like to suggest that we introduce a new layer just beneath the
> JCR API for getting rid of or reducing the above drawbacks. This layer
> would consist of the following three parts:
>
>     1) Set of abstract AbstractSession, AbstractItem, etc. classes that
>        implement as much of the respective JCR interfaces using nothing
>        else but calls to other JCR methods. These would be just like the
>        AbstractMap, etc. classes in java.util.
>
>     2) Set of QSession, QItem, etc. (or with some better naming) interfaces
>        that declare QName and Path versions of those JCR methods that can't
>        reasonably be implemented by the above abstract classess. Potentially
>        we could also break strict one-to-one correspondence with the JCR
>        interfaces to allow for better separation of concerns.
>
>     3) Set of adapter (or facade) classes that extend the above abstract
>        classes and implement the remaining methods using name mapping and
>        implementations of the above interfaces. These classes could also
>        take care of backreferences like Session.getRepository() and
>        Item.getSession().
>
> All these parts could be implemented within jackrabbit-jcr-commons so
> that they can be reused in other JCR implementations, for example in
> the client part of the SPI project.
>
> The current Impl classes in jackrabbit-core would be refactored to
> implement the above interfaces instead of the standard JCR interfaces.
>
> What do you think? At least the first part of the proposal should be
> easy to implement incrementally without destabilizing anything. The
> granularity of implementing the other parts is a bit bigger, but could
> still be performed just one interface at a time.
>
> BR,
>
> Jukka Zitting
>


-- 
-----------------------------------------< tobias.bocanegra@day.com >---
Tobias Bocanegra, Day Management AG, Barfuesserplatz 6, CH - 4001 Basel
T +41 61 226 98 98, F +41 61 226 98 97
-----------------------------------------------< http://www.day.com >---