Dan Diephouse wrote:
Looking good. But even more new comments! Hopefully you aren't sick of
me yet :-)
Never! Of course, large payments of small unmarked bills would help ;-)
Can we collapse ServiceContext and Provider? I would propose then that
Provider gets getters/setters for Resolver<Subject>/<Target>. If we did
this we could get rid of ServiceContext too I think -- which would
remove one more step for the user. I did a similar thing with when I
made it implement Resolver<Target>. While I think this should be
pluggable, I really think users should not have to configure a resolver
by default.
Quite possibly. Will take a look today.
Along these lines I think we should remove the instantiation code which
is in DefaultServiceContext. IMO this is the job of a container of some
sort. I mean container in the broadest sense here. For instance, I
think it could be wrapped up in something like a
PropertiesProviderBuilder. It could then configure a whole provider
instance - including resolvers, workspace manager, and
collectionadapters.
Agreed.
Transactional.begin/end needs to take RequestContext so I can store a
JCR session in it.
Ok, will add that today.
The JCR tests provide a good means to test if the basic ServiceProvider
stuff I wrote still roughly works.
Well, it would need to be ported to the new model as the interfaces have
changed. Would you like to take a stab at that? Doing so would help
you get a better feeling for the new design.
My feeling is that CollectionInfo should not extend CollectionAdapter.
While I agree that people will probably implement both CollectionInfo
and CollectionAdapter by default, sometimes you want to just return the
metadata.
Agreed. CollectionInfo can have a getCollectionAdapter method to
connect the two.
Re: BasicAdapter - I'm still unconvinced about this API and its ability
to support the necessary semantics for generic APP stores.
Ditto.
CollectionAdapterManager should be in the basic package if we keep the
basic stuff around.
Take another look at CAM; I modified it so that it works generically
with any CollectionAdapter, not just BasicAdapter. This would allow any
Provider implementation to use the properties file deployment mechanism
independently of whether the BasicAdapter interface is used.
I get the feeling that
WorkspaceManager.checkMethod/checkTarget/getMethods can all probably go.
Could we not work that logic into the CollectionAdapter.extensionRequest
?
Not sure about this.
I still don't think its a good idea for a Provider to act as its own
WorkspaceManager per my previous email.
Noted, but it does make things easier in some cases (see the Simple
example). However, the design assumes they are separate things.
Shouldn't the WorkspaceInfo logic in DefaultProvider be in
WorkspaceManager?
Possibly; will take another look.
- James
- Dan
James M Snell wrote:
Ok, the server refactoring is coming along very well I think. Thus
far, I've been able to greatly simplify the overall design, as well as
integrate the approaches implemented by Dan and the google feed-server
team while still maintaining the flexibility of the original framework.
The main components of the refactored design are:
* AbderaServlet
* ServiceContext
* Provider
* WorkspaceManager
* CollectionAdapter
* RequestContext
* ResponseContext
* Target
* Resolver<Target>
* Resolver<Subject>
For the overwhelming majority of implementations, all an end developer
will need to do is implement a CollectionAdapter, provide a
TargetResolver, and glue the two together using a ServiceContext.
The examples in the server_refactor test cases illustrates the three
fundamental approaches.
The application flow is simple:
* The AbderaServlet receives a request and creates a ServiceContext
* The ServiceContext creates a Provider instance
* The Provider instance uses it's associated WorkspaceManager to
select a CollectionAdapter.
* Once the CollectionAdapter is selected, the Provider forwards the
request on to the appropriate method
In some cases, the Provider and the WorkspaceManager will be the same
object. In other cases, the Provider and the WorkspaceManager will be
separate.
Simple
------
In the Simple example, the developer implements a CollectionAdapter, a
Provider and a ServiceContext.
The CollectionAdapter provides the guts of the implementation,
providing implementations for each of the main prototocol operations
such as getFeed, getEntry, etc. These are the methods that used to
exist on the old style provider interface.
The Provider extends AbstractWorkspaceProvider which means the
Provider is acting as it's own WorkspaceManager.
The Provider/WorkspaceManager dispatches requests to the SimpleAdapter
implementation.
The SimpleServiceContext glues the Provider to the appropriate target
resolver.
Default
-------
In the Default example, the developer uses the same CollectionAdapter
implementation used in the simple example but uses the DefaultProvider
class.
The Default example is similar in nature to the CollectionProvider
stuff implemented by Dan in that it is the DefaultProvider's job to
handle things like the creation of the Service document based on
metadata provided by the developer.
The simple and default examples are nearly identical with the
exception that the default example supports multiple workspaces and
collections.
Basic
-----
The basic example (which is poorly named, I know) is essentially the
google feed-server stuff, slightly modified so that it sits on top of
the default provider implementation.
The properties file based deployment is kept intact, but the Adapter
interface is replaced by the BasicAdapter abstract class, which is an
abstract CollectionAdapter implementation that defines the same
abstract methods defined by the google feed-server Adapter interface.
Existing google feed-server Adapter implementations can be ported to
this design simply by replacing "implements Adapter" with "extends
BasicAdapter".
The implementation has been further modified to support the creation
of a service document. The code will read all of the *.properties
files for the adapters and will generate a service document with one
workspace and one collection per configured adapter.
Service Documents
-----------------
In this design, the Provider is responsible for serving the service
documents. This means that the service document support will vary
depending on the capabilities of the Provider implementation.
CollectionAdapters
------------------
In each of the three approaches, the same CollectionAdapter interface
is used. Also, with the possible exception of URI patterns used for
links, CollectionAdapters should be independent of the Provider
implementation used. We need to find a more elegant way of tying
Target Resolvers and Collection Adapters together while at the same
time making it easier to manage links, but that can come later. The
more important thing is that once a CollectionAdapter is
implementation, we should be able to use it regardless of which of the
three models are selected.
Media Collections
-----------------
The basic CollectionAdapter interface does not support media
operations. If you want to implement support for media collections,
the CollectionAdapter has to implement the MediaCollectionAdapter
interface. The reason for this separation is to reduce the complexity
of the simplest Atompub implementations that will only ever support
Atom entries.
Transactional
-------------
CollectionAdapter implementations can implement the Transactional
interface if they wish to support transactional start/end/compensate
semantics. Provider implementations SHOULD call Transactional.start()
before delegating to the CollectionAdapter method and
Transactional.end() after delegating. If an error occurs, the
Provider SHOULD call Transactional.compensate().
- James