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 2009/09/03 16:00:55 UTC

Jackrabbit management API

Hi,

Let's branch some of the more general discussion from JCR-1865 to here on dev@.

The issue is about repository management operations like starting and
stopping the repository, changing repository configuration, etc. that
are typically only available to administrators. It would be nice if
these operations could be accessed through mechanisms like JMX for
easy integration with various network and server management and
monitoring tools.

The question is, should such an API be implemented by extending the
existing JCR Repository and Session interfaces for easy access over
layers like JCR-RMI and SPI, or should it be a separate interface that
is only exposed to selected clients? The former approach requires some
extra administrator-level access controls and might be more difficult
to integrate with JMX, while the latter approach requires extra
configuration and won't benefit from our existing remoting mechanisms.
It might also be possible to merge these approaches somehow, for
example with a method like
JackrabbitRepository.getRepositoryManager(Credentials).

A related consideration is what we are going to do with OSGi. The OSGi
bundle lifecycle and configuration mechanisms offer much of the same
functionality as proposed above, and there are already things like JMX
integration for OSGi.

BR,

Jukka Zitting

Re: Jackrabbit management API

Posted by Thomas Müller <th...@day.com>.
Hi again,

Regarding access control: I think we should use the JCR access control
mechanism, meaning that only authorized sessions can do certain
operations. Relying on other mechanisms doesn't make sense for me,
because it restricts what kind of applications can use such methods.
For example: A standalone tool should be able to trigger garbage
collection. The tools should be able to use the JCR 2.0 API to get the
repository, no matter if the repository is installed locally or on a
remote server.

The JCR API already provides a number of 'management' features, such
as creating workspaces, node type management, namespace registry, and
so forth. Whatever API we invent, it should be similar to the existing
API. For two reasons: it's more consistent with the Jackrabbit API,
and it can later be included in the next JCR API.

Regards,
Thomas


On Thu, Sep 3, 2009 at 4:19 PM, Thomas Müller<th...@day.com> wrote:
> Hi,
>
> The solution should be compliant with the JCR 2.0 API (specially
> regarding creating Repository objects).
>
> We should use interfaces and no 'hard coded' classes. There are two reasons:
>
> 1) with interfaces, we can add 'wrappers' or 'proxies' around an
> implementation such as a logging layer, a virtual repository that can
> combine multiple repositories into one, or a remoting layer.
>
> 2) with interfaces, applications can be written in an
> implementation-independent way, so that the exact same code (without
> having to recompile) can run against many implementations. One example
> is a generic JCR browser tool.
>
> I don't think that we should _rely_ on a specific mechanism such as
> JMX, JNDI, OSGi, Spring and so on. Any such mechanism should be
> orthogonal to the Jackrabbit API.
>
> Regards,
> Thomas
>
>
>
> On Thu, Sep 3, 2009 at 4:00 PM, Jukka Zitting<ju...@gmail.com> wrote:
>> Hi,
>>
>> Let's branch some of the more general discussion from JCR-1865 to here on dev@.
>>
>> The issue is about repository management operations like starting and
>> stopping the repository, changing repository configuration, etc. that
>> are typically only available to administrators. It would be nice if
>> these operations could be accessed through mechanisms like JMX for
>> easy integration with various network and server management and
>> monitoring tools.
>>
>> The question is, should such an API be implemented by extending the
>> existing JCR Repository and Session interfaces for easy access over
>> layers like JCR-RMI and SPI, or should it be a separate interface that
>> is only exposed to selected clients? The former approach requires some
>> extra administrator-level access controls and might be more difficult
>> to integrate with JMX, while the latter approach requires extra
>> configuration and won't benefit from our existing remoting mechanisms.
>> It might also be possible to merge these approaches somehow, for
>> example with a method like
>> JackrabbitRepository.getRepositoryManager(Credentials).
>>
>> A related consideration is what we are going to do with OSGi. The OSGi
>> bundle lifecycle and configuration mechanisms offer much of the same
>> functionality as proposed above, and there are already things like JMX
>> integration for OSGi.
>>
>> BR,
>>
>> Jukka Zitting
>>
>

Re: Jackrabbit management API

Posted by Thomas Müller <th...@day.com>.
Hi,

>> One solution would be: JackrabbitRepository.shutdown(Session s).
>
> that would e.g. require that a container that controls the lifecycle
> of the repository needs credentials to start and stop it. I don't
> think that useful.

I understand. So the problem is that the application that started the
repository should be able to stop it. What about:

JackrabbitRepository.shutdown(java.util.Map parameters)
Where parameters need to be the same parameters that were used to
start the repository. Or:
JackrabbitRepository.shutdown(RepositoryFactory createdBy)
or:
JackrabbitRepositoryFactory.shutdown(Repository rep)
or:
JackrabbitRepositoryFactory.getManager(Repository rep)

Regards,
Thomas

Re: Jackrabbit management API

Posted by Marcel Reutegger <ma...@gmx.net>.
On Thu, Sep 3, 2009 at 17:43, Thomas Müller<th...@day.com> wrote:
> Creating the Repository object is specified in the JCR 2.0 API, and I
> don't see why Jackrabbit can't be compliant.

getting or creating a repository object does not necessarily mean
starting the repository. the latter is what Jukka means with lifecycle
(IIUC).

JSR 283 only specifies how you get an instance of Repository. it does
not specify anything that allows you to *control* when a repository is
started or stoppped.

> Repository shutdown is not specified in the JCR 2.0 API, however for
> that we have the Jackrabbit API. The current mechanism is
> JackrabbitRepository.shutdown(). There is no access control, which is
> bad.

I don't think so. a shutdown method with a session is not symmetric.
otherwise you would also have to control if someone is allowed to
start a repository.

> One solution would be: JackrabbitRepository.shutdown(Session s).

that would e.g. require that a container that controls the lifecycle
of the repository needs credentials to start and stop it. I don't
think that useful.

> There are other solutions, but in any case this shouldn't affect how
> you _get_ the repository object.

agreed. if you just want to get a repository instance you use RepositoryFactory.

regards
 marcel

Re: Jackrabbit management API

Posted by Alexander Klimetschek <ak...@day.com>.
On Tue, Sep 8, 2009 at 11:54, Jukka Zitting<ju...@gmail.com> wrote:
>> What if I want to use the log wrapper on the server side?
>
> Just use it. Just like a log wrapper can support
> JackrabbitRepositoryFactory.shutdown() it can support
> RepositoryManager.start().

But the log wrapper would be Jackrabbit-specific then.

Regards,
Alex

-- 
Alexander Klimetschek
alexander.klimetschek@day.com

Re: Jackrabbit management API

Posted by Thomas Müller <th...@day.com>.
Hi,

> But the log wrapper would be Jackrabbit-specific then.

With Jukkas approach, it would, and with my approach, it wouldn't.

Regards,
Thomas

Re: Jackrabbit management API

Posted by Thomas Müller <th...@day.com>.
Hi,

Jukka and me discussed the problem last week in person, and I think we
found a solution.

I have posted a new patch at https://issues.apache.org/jira/browse/JCR-1865

This patch should include the Jackrabbit API additions. The
implementation is still incomplete, for example
org.apache.jackrabbit.core.jndi.RepositoryFactoryImpl doesn't
implement JackrabbitRepositoryFactory yet. Also JackrabbitRepository
still has a public shutdown() method - we should probably deprecate or
remove it. Remove, because this method is insecure (anybody can call
it).

Regards,
Thomas





On Tue, Sep 8, 2009 at 5:46 PM, Jukka Zitting <ju...@gmail.com> wrote:
> Hi,
>
> On Tue, Sep 8, 2009 at 5:00 PM, Thomas Müller<th...@day.com> wrote:
>> Jukka, it seems that you don't understand what I mean.
>
> Yeah, we're probably talking past each other. :-}
>
>>> Simply by instantiating the appropriate implementation class, for
>>> example like this:
>>>
>>>    RepositoryManager manager = new RepositoryManagerImpl(config);
>>
>> That's not acceptable, as it's not JCR 2.0 API compliant.
>
> This is code that we would write in a component like
> jackrabbit-standalone. Are you saying that we shouldn't write
> Jackrabbit-specific code in Jackrabbit? :-)
>
> Your own proposals all included a Class.forName(...).newInstance()
> call with a Jackrabbit-specific implementation class. Similarly, if
> one really wanted, the above code could be replaced with:
>
>    RepositoryManager manager =
>        (RepositoryManager) Class.forName(...).newInstance();
>
> ... and a change to the RepositoryManager interface to accept
> configuration settings after instantiation.
>
> Personally I don't see the use case where something like that would be needed.
>
>>> The server is in any case implementation-specific,
>>
>> No, it is not.
>
> Sure it is, the code is a part of Jackrabbit.
>
>> I don't understand why the standard JCR 2.0 way can't
>> be used. Please tell me. Why can't the 'server' / 'listener' be
>> started when you get the repository (see above).
>
> Because the RepositoryFactory API was never designed for this. The
> getRepository() method is documented to "*establish a connection* to a
> repository using the given parameters" (emphasis added).
>
> We can of course extend the API by defining
> JackrabbitRepositoryFactory with the added methods like shutdown()
> needed to properly control the repository lifecycle, but that's
> already beyond the scope of JCR.
>
> The reason why I prefer an interface that does *not* extend existing
> JCR interfaces is to avoid extra complexity in things like JMX
> mappings. If people like that, I certainly wouldn't mind an extra
> method like in your proposal [C].
>
> Or our implementation class could implement both RepositoryFactory and
> RepositoryManager, making the relevant part of your proposal [B] look
> like this:
>
>    5) if (factory instanceof RepositoryManager)
>           ((RepositoryManager) factory).stop();
>
>>>    RepositoryManager manager =
>>>        new LoggingRepositoryManager(new RepositoryManagerImpl(config));
>>
>> This is Jackrabbit-specific.
>
> Where's the Jackrabbit-specific part in:
>
>    public class LoggingRepositoryManager implements RepositoryManager {
>
>        private static final Logger log =
>            LoggerFactory.getLogger(LoggingRepositoryManager.class);
>
>        private final RepositoryManager manager;
>
>        public LoggingRepositoryManager(RepositoryManager manager) {
>            this.manager = manager;
>        }
>
>        public boolean isRunning() {
>            log.debug("isRunning()");
>            return manager.isRunning();
>        }
>
>        public boolean start() {
>            log.debug("start()");
>            manager.start();
>        }
>
>        public boolean stop() {
>            log.debug("stop()");
>            manager.stop();
>        }
>
>    }
>
> BR,
>
> Jukka Zitting
>

Re: Jackrabbit management API

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

On Tue, Sep 8, 2009 at 5:00 PM, Thomas Müller<th...@day.com> wrote:
> Jukka, it seems that you don't understand what I mean.

Yeah, we're probably talking past each other. :-}

>> Simply by instantiating the appropriate implementation class, for
>> example like this:
>>
>>    RepositoryManager manager = new RepositoryManagerImpl(config);
>
> That's not acceptable, as it's not JCR 2.0 API compliant.

This is code that we would write in a component like
jackrabbit-standalone. Are you saying that we shouldn't write
Jackrabbit-specific code in Jackrabbit? :-)

Your own proposals all included a Class.forName(...).newInstance()
call with a Jackrabbit-specific implementation class. Similarly, if
one really wanted, the above code could be replaced with:

    RepositoryManager manager =
        (RepositoryManager) Class.forName(...).newInstance();

... and a change to the RepositoryManager interface to accept
configuration settings after instantiation.

Personally I don't see the use case where something like that would be needed.

>> The server is in any case implementation-specific,
>
> No, it is not.

Sure it is, the code is a part of Jackrabbit.

> I don't understand why the standard JCR 2.0 way can't
> be used. Please tell me. Why can't the 'server' / 'listener' be
> started when you get the repository (see above).

Because the RepositoryFactory API was never designed for this. The
getRepository() method is documented to "*establish a connection* to a
repository using the given parameters" (emphasis added).

We can of course extend the API by defining
JackrabbitRepositoryFactory with the added methods like shutdown()
needed to properly control the repository lifecycle, but that's
already beyond the scope of JCR.

The reason why I prefer an interface that does *not* extend existing
JCR interfaces is to avoid extra complexity in things like JMX
mappings. If people like that, I certainly wouldn't mind an extra
method like in your proposal [C].

Or our implementation class could implement both RepositoryFactory and
RepositoryManager, making the relevant part of your proposal [B] look
like this:

    5) if (factory instanceof RepositoryManager)
           ((RepositoryManager) factory).stop();

>>    RepositoryManager manager =
>>        new LoggingRepositoryManager(new RepositoryManagerImpl(config));
>
> This is Jackrabbit-specific.

Where's the Jackrabbit-specific part in:

    public class LoggingRepositoryManager implements RepositoryManager {

        private static final Logger log =
            LoggerFactory.getLogger(LoggingRepositoryManager.class);

        private final RepositoryManager manager;

        public LoggingRepositoryManager(RepositoryManager manager) {
            this.manager = manager;
        }

        public boolean isRunning() {
            log.debug("isRunning()");
            return manager.isRunning();
        }

        public boolean start() {
            log.debug("start()");
            manager.start();
        }

        public boolean stop() {
            log.debug("stop()");
            manager.stop();
        }

    }

BR,

Jukka Zitting

Re: Jackrabbit management API

Posted by Thomas Müller <th...@day.com>.
Hi,

Jukka, it seems that you don't understand what I mean.

> Simply by instantiating the appropriate implementation class, for
> example like this:
>
>    RepositoryManager manager = new RepositoryManagerImpl(config);

That's not acceptable, as it's not JCR 2.0 API compliant. Again, the
JCR API 2.0 compliant way to create a repository is:

RepositoryFactory factory = (RepositoryFactory)
Class.forName(factoryClass).newInstance();
Repository rep = factory.getRepository(parameters);

>From here, it's possible to get the RepositoryManager
(RepositoryManager, an interface, _not_ RepositoryManagerImpl, a
specific class) using: [A], [B] or [C] as I wrote above. If this is a
problem, why?

> The server is in any case implementation-specific,

No, it is not. I don't understand why the standard JCR 2.0 way can't
be used. Please tell me. Why can't the 'server' / 'listener' be
started when you get the repository (see above).

> so using a concrete class is no problem.

Again, it _is_ a problem. I repeat what I wrote at the beginning: We
should use interfaces and no 'hard coded' classes. There are two
reasons:

1) with interfaces, we can add 'wrappers' or 'proxies' around an
implementation such as a logging layer, a virtual repository that can
combine multiple repositories into one, or a remoting layer.

2) with interfaces, applications can be written in an
implementation-independent way, so that the exact same code (without
having to recompile) can run against many implementations. One example
is a generic JCR browser tool.

> Using a decorator like a logging wrapper is trivial:

Don't use "trivial" or "simply", please.

>    RepositoryManager manager =
>        new LoggingRepositoryManager(new RepositoryManagerImpl(config));

This is Jackrabbit-specific. That means the logging wrapper, as well
as the application, would need to know about a specific CLASS of
Jackrabbit. Not an Interface, a CLASS. I think that's not acceptable.

Regards,
Thomas

Re: Jackrabbit management API

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

On Tue, Sep 8, 2009 at 2:06 PM, Thomas Müller<th...@day.com> wrote:
> How would you instantiate the RepositoryManager object on the server side?

Simply by instantiating the appropriate implementation class, for
example like this:

    RepositoryManager manager = new RepositoryManagerImpl(config);

The server is in any case implementation-specific, so using a concrete
class is no problem.

Using a decorator like a logging wrapper is trivial:

    RepositoryManager manager =
        new LoggingRepositoryManager(new RepositoryManagerImpl(config));

On Tue, Sep 8, 2009 at 3:09 PM, Alexander Klimetschek<ak...@day.com> wrote:
> But the log wrapper would be Jackrabbit-specific then.

It obviously depends on jackrabbit-api, but so would a logging wrapper
for any of the other proposed approaches.

BR,

Jukka Zitting

Re: Jackrabbit management API

Posted by Thomas Müller <th...@day.com>.
Hi,

How would you instantiate the RepositoryManager object on the server side?

Regards,
Thomas


On Tue, Sep 8, 2009 at 11:54 AM, Jukka Zitting<ju...@gmail.com> wrote:
> Hi,
>
> On Tue, Sep 8, 2009 at 11:43 AM, Thomas Müller<th...@day.com> wrote:
>> What about embedded usage?
>
> Then you don't need the management API as the application already has
> direct control over the repository instance. If you want, you can use
> the management API for that control or even expose it to external
> management clients, but that's by no means mandatory.
>
>> What if I want to use the log wrapper on the server side?
>
> Just use it. Just like a log wrapper can support
> JackrabbitRepositoryFactory.shutdown() it can support
> RepositoryManager.start().
>
> BR,
>
> Jukka Zitting
>

Re: Jackrabbit management API

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

On Tue, Sep 8, 2009 at 11:43 AM, Thomas Müller<th...@day.com> wrote:
> What about embedded usage?

Then you don't need the management API as the application already has
direct control over the repository instance. If you want, you can use
the management API for that control or even expose it to external
management clients, but that's by no means mandatory.

> What if I want to use the log wrapper on the server side?

Just use it. Just like a log wrapper can support
JackrabbitRepositoryFactory.shutdown() it can support
RepositoryManager.start().

BR,

Jukka Zitting

Re: Jackrabbit management API

Posted by Thomas Müller <th...@day.com>.
Hi,

> An *application* (i.e. a normal JCR client) doesn't need to call
> start(), as the repository is normally already running as a separate
> server, webapp or another resource when the application wants to
> access it.

What about embedded usage?

What if I want to use the log wrapper on the server side?

Regards,
Thomas

Re: Jackrabbit management API

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

On Tue, Sep 8, 2009 at 11:16 AM, Thomas Müller<th...@day.com> wrote:
>>> Using your proposal, an application would have to call
>>> RepositoryManager.start() to be able to use the repository, right?
>>
>> No.
>
> Was this the answer to my question? "No" meaning start() does not need
> to be called to start the repository? Why do you have start() then?

An *application* (i.e. a normal JCR client) doesn't need to call
start(), as the repository is normally already running as a separate
server, webapp or another resource when the application wants to
access it.

The use case is being able to remotely manage for example a
jackrabbit-standalone process without shell scripts accessing the
server where the repository is running. This has nothing to do with
normal RepositoryFactory.getRepository() calls.

BR,

Jukka Zitting

Re: Jackrabbit management API

Posted by Thomas Müller <th...@day.com>.
Hi,

>> Using your proposal, an application would have to call
>> RepositoryManager.start() to be able to use the repository, right?
>
> No.

Was this the answer to my question? "No" meaning start() does not need
to be called to start the repository? Why do you have start() then?

Regards,
Thomas

Re: Jackrabbit management API

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

On Tue, Sep 8, 2009 at 11:04 AM, Thomas Müller<th...@day.com> wrote:
> Using your proposal, an application would have to call
> RepositoryManager.start() to be able to use the repository, right?

No. A management API is typically only needed for deployments like
jackrabbit-standalone, -webapp, and -jca where the JCR client is
separate from the repository server.

Normal JCR clients can and will in all these cases simply use the
standard RepositoryFactory API to access the repository and would
never need to worry about the management features.

BR,

Jukka Zitting

Re: Jackrabbit management API

Posted by Thomas Müller <th...@day.com>.
Hi Jukka,

> I still don't understand this requirement. JCR does not specify a
> mechanism to shutdown the repository, so by definition a feature like
> this can't be JCR-compatible.

I repeat what I wrote before:

"[1] If the mechanism is incompatible, then the application can not
easily use repository wrappers such as a log wrapper, use a JCR
remoting implementation, or use a different JCR implementation."

Using your proposal, an application would have to call
RepositoryManager.start() to be able to use the repository, right? If
this is the case, an application _could_ _not_ be written in a
Jackrabbit independent way. This is not acceptable. Jackrabbit would
simply not be JCR spec compliant.

I think it's important that we all understand this point.

Regards,
Thomas

Re: Jackrabbit management API

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

On Tue, Sep 8, 2009 at 10:10 AM, Thomas Müller<th...@day.com> wrote:
> The shutdown mechanism needs to be compatible with the JCR API [1].

I still don't understand this requirement. JCR does not specify a
mechanism to shutdown the repository, so by definition a feature like
this can't be JCR-compatible.

Instead of extending the JCR RepositoryFactory interface to do
something like this, I'd simply add a new plain and simple
RepositoryManager interface:

    public interface RepositoryManager {
        boolean isRunning();
        void start() throws RepositoryException;
        void stop() throws RepositoryException;
    }

You can still make such a manager accessible via one of our JCR
extension interfaces through a getRepositoryManager() method, but
there are many likely deployment scenarios (OSGi service references,
JNDI lookups, JMX and SNMP bindings, etc.) where it's beneficial if
you *don't* need to go through the JCR API to be able to control the
repository

BR,

Jukka Zitting

Re: Jackrabbit management API

Posted by Thomas Müller <th...@day.com>.
Hi,

> Or more general:
>
> 5) if (factory instanceof RepositoryManagerFactory)
> ((RepositoryControllerFactory)
> factory).getRepositoryManager(rep).shutdown();
>
> with
>
> interface RepositoryManagerFactory {
>  RepositoryManager getRepositoryManager(Repository r);
> }

I forgot to write that JackrabbitRepositoryFactory is an interface, so
this is the same as my [C], but using different interface names. I
chose JackrabbitRepositoryFactory because most interfaces in
jackrabbit-api start with "Jackrabbit".

Regards,
Thomas

Re: Jackrabbit management API

Posted by Michael Dürig <mi...@day.com>.
> [C] == Shutdown using Factory.getRepositoryManager(Repository).shutdown ==
> 
> 1) Properties parameters = ...
> 2) String factoryClass = parameters.remove("factory").toString();
> 3) RepositoryFactory factory = (RepositoryFactory)
> Class.forName(factoryClass).newInstance();
> 4) Repository rep = factory.getRepository(parameters);
> 5) if (factory instanceof JackrabbitRepositoryFactory)
> ((JackrabbitRepositoryFactory)
> factory).getRepositoryManager(rep).shutdown();
> 

Or more general:

5) if (factory instanceof RepositoryManagerFactory)
((RepositoryControllerFactory)
factory).getRepositoryManager(rep).shutdown();

with

interface RepositoryManagerFactory {
   RepositoryManager getRepositoryManager(Repository r);
}

Michael



Re: Jackrabbit management API

Posted by Thomas Müller <th...@day.com>.
Hi,

So let's say we want a new, secure mechanism to 'stop' a repository,
without having to login. Secure meaning only the module that created
the repository object may call shutdown. The current mechanism
(JackrabbitRepository.shutdown()) doesn't provide this security, as
any client that has access to the Repository object can call it:
((JackrabbitRepository)rep).shutdown().

If the application doesn't call the secure shutdown method, the
repository should still shutdown when the application ends at the
latest.

The shutdown mechanism needs to be compatible with the JCR API [1].
That means an application must be able to call shutdown if the
application created the Repository object using a RepositoryFactory.
An application may have to import the Jackrabbit API, and use
instanceof and casts:

if (x instanceof JackrabbitSomething) {
   ... .shutdown(...)
}

[1] If the mechanism is incompatible, then the application can not
easily use repository wrappers such as a log wrapper, use a JCR
remoting implementation, or use a different JCR implementation.

There are multiple ways to achieve that:

[A] == Shutdown using Factory.shutdown(Repository) ==

1) Properties parameters = ...
2) String factoryClass = parameters.remove("factory").toString();
3) RepositoryFactory factory = (RepositoryFactory)
Class.forName(factoryClass).newInstance();
4) Repository rep = factory.getRepository(parameters);
5) if (factory instanceof JackrabbitRepositoryFactory)
((JackrabbitRepositoryFactory) factory).shutdown(rep);

Lines 1) - 4) are a JCR API compliant way to get / start a repository.
If we can't support that for Jackrabbit, then the application can't be
written in an implementation-independent way, and we can't achieve the
goal [1].

Line 5) is Jackrabbit specific. This is more secure than shutdown()
because an application needs to have access to the factory instance
that created the repository. A regular application will only have
access to the Repository object, and can't call the method, or call
it, but the call will fail because the repository keeps a reference to
the factory that created it, and we can verify it's the same object
within the Jackrabbit implementation.

[B] == Shutdown using Repository.shutdown(Factory) ==

1) Properties parameters = ...
2) String factoryClass = parameters.remove("factory").toString();
3) RepositoryFactory factory = (RepositoryFactory)
Class.forName(factoryClass).newInstance();
4) Repository rep = factory.getRepository(parameters);
5) if (rep instanceof JackrabbitRepository) ((JackrabbitRepository)
rep).shutdown(factory);

[C] == Shutdown using Factory.getRepositoryManager(Repository).shutdown ==

1) Properties parameters = ...
2) String factoryClass = parameters.remove("factory").toString();
3) RepositoryFactory factory = (RepositoryFactory)
Class.forName(factoryClass).newInstance();
4) Repository rep = factory.getRepository(parameters);
5) if (factory instanceof JackrabbitRepositoryFactory)
((JackrabbitRepositoryFactory)
factory).getRepositoryManager(rep).shutdown();

Regards,
Thomas

Re: Jackrabbit management API

Posted by Guo Du <mr...@gmail.com>.
On Thu, Sep 3, 2009 at 4:43 PM, Thomas Müller<th...@day.com> wrote:
>> Think of the complexity of controlling the lifecycle of Derby that
>> uses the DriverManager API in JDBC to startup and shutdown the
>> database.
>
> Other databases provide betters ways. For HSQLDB and H2, you close the
> database by executing the SQL statement SHUTDOWN. This doesn't even
> require any new Java API. H2 by default closes the database when the
> last connection is closed (like TransientRepository), which is not
> always what you want, but OK. There is also a mechanism to specify a
> 'close delay'.

JCR is very much like a database. The jackrabbit repository host is
much like a embed database, and once it's running, it will act as a db
server for remote client. The life cycle could be managed as database.

1. For repository host
The shutdown method is already exist at least from 1.5.6 at
org.apache.jackrabbit.api.JackrabbitRepository.shutdown(). We just
need another method in JackrabbitRepository to be able to explicit
start up a the repository. For TransientRepository, we just need
expose the exist method startRepository as startup.

2. For remote client
I don't think it's necessary to expose the lifecycle management to
remote client, compare with database, a client is not suppose to
startup/shutdown db server. Client shouldn't even depends on
Jackrabbit API, such as developer normally only deal jdbc instead of
vendor jdbc api.

-Guo

Re: Jackrabbit management API

Posted by Thomas Müller <th...@day.com>.
Hi,

>> The solution should be compliant with the JCR 2.0 API (specially
>> regarding creating Repository objects).
>
> It can't be compliant, as the repository lifecycle is outside the
> scope of JCR 2.0.

Creating the Repository object is specified in the JCR 2.0 API, and I
don't see why Jackrabbit can't be compliant.

Repository shutdown is not specified in the JCR 2.0 API, however for
that we have the Jackrabbit API. The current mechanism is
JackrabbitRepository.shutdown(). There is no access control, which is
bad. One solution would be: JackrabbitRepository.shutdown(Session s).
There are other solutions, but in any case this shouldn't affect how
you _get_ the repository object.

> You can use the RepositoryFactory to get reference
> to a Repository instance, but that API is hardly sufficient for
> controlling the lifecycle of the repository.

Why? What's the problem?

> Think of the complexity of controlling the lifecycle of Derby that
> uses the DriverManager API in JDBC to startup and shutdown the
> database.

Derby is a very bad example: to close a database, you need to call
DriverManager.getConnection. It just doesn't make any sense.

Other databases provide betters ways. For HSQLDB and H2, you close the
database by executing the SQL statement SHUTDOWN. This doesn't even
require any new Java API. H2 by default closes the database when the
last connection is closed (like TransientRepository), which is not
always what you want, but OK. There is also a mechanism to specify a
'close delay'.

Regards,
Thomas

Re: Jackrabbit management API

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

On Thu, Sep 3, 2009 at 4:19 PM, Thomas Müller<th...@day.com> wrote:
> The solution should be compliant with the JCR 2.0 API (specially
> regarding creating Repository objects).

It can't be compliant, as the repository lifecycle is outside the
scope of JCR 2.0. You can use the RepositoryFactory to get reference
to a Repository instance, but that API is hardly sufficient for
controlling the lifecycle of the repository.

Think of the complexity of controlling the lifecycle of Derby that
uses the DriverManager API in JDBC to startup and shutdown the
database. It's doable, but not very pretty. The way I see it, we
should rather use RepositoryFactory as a way to access an already
existing repository.

> We should use interfaces and no 'hard coded' classes. There are two reasons:

Exactly, that's why I'm proposing a management API.

> I don't think that we should _rely_ on a specific mechanism such as
> JMX, JNDI, OSGi, Spring and so on. Any such mechanism should be
> orthogonal to the Jackrabbit API.

Agreed, though the API should be designed to support easy integration
with such technologies.

BR,

Jukka Zitting

Re: Jackrabbit management API

Posted by Thomas Müller <th...@day.com>.
Hi,

The solution should be compliant with the JCR 2.0 API (specially
regarding creating Repository objects).

We should use interfaces and no 'hard coded' classes. There are two reasons:

1) with interfaces, we can add 'wrappers' or 'proxies' around an
implementation such as a logging layer, a virtual repository that can
combine multiple repositories into one, or a remoting layer.

2) with interfaces, applications can be written in an
implementation-independent way, so that the exact same code (without
having to recompile) can run against many implementations. One example
is a generic JCR browser tool.

I don't think that we should _rely_ on a specific mechanism such as
JMX, JNDI, OSGi, Spring and so on. Any such mechanism should be
orthogonal to the Jackrabbit API.

Regards,
Thomas



On Thu, Sep 3, 2009 at 4:00 PM, Jukka Zitting<ju...@gmail.com> wrote:
> Hi,
>
> Let's branch some of the more general discussion from JCR-1865 to here on dev@.
>
> The issue is about repository management operations like starting and
> stopping the repository, changing repository configuration, etc. that
> are typically only available to administrators. It would be nice if
> these operations could be accessed through mechanisms like JMX for
> easy integration with various network and server management and
> monitoring tools.
>
> The question is, should such an API be implemented by extending the
> existing JCR Repository and Session interfaces for easy access over
> layers like JCR-RMI and SPI, or should it be a separate interface that
> is only exposed to selected clients? The former approach requires some
> extra administrator-level access controls and might be more difficult
> to integrate with JMX, while the latter approach requires extra
> configuration and won't benefit from our existing remoting mechanisms.
> It might also be possible to merge these approaches somehow, for
> example with a method like
> JackrabbitRepository.getRepositoryManager(Credentials).
>
> A related consideration is what we are going to do with OSGi. The OSGi
> bundle lifecycle and configuration mechanisms offer much of the same
> functionality as proposed above, and there are already things like JMX
> integration for OSGi.
>
> BR,
>
> Jukka Zitting
>