Christopher Elkins wrote:
>
> Brett McLaughlin [[EMAIL PROTECTED]] wrote:
> > In light of the increasing amount of services, I make the following
> > proposal for service redesign. Hopefully this starts to give people an
> > idea of what I have in mind for Turbine 1.0 final, or even 2.0. This is
> >
> I don't see any reason why we can't implement these changes ASAP after
> discussion. Sure, we'll have to fix minor breakages with existing services,
> but that's nothing insurmountable.
>
> >
> <..snip..>
> >
> > Redefinition of the Service interface:
> >
> > public interface Service {
> >
> > public void setName(String name);
> >
> > public String getName();
> >
> > public void init(Object ob);
> >
> > public Object get();
> >
> > public boolean execute() throws ServiceException;
> >
> I understand the distinction between get() and execute(), but is it
> implicit that for some services one of these methods might do nothing? For
> instance, a JDBC Connection service has no identifiable "execute" behavior.
> Therefore, would a call to execute() always return true (after checking that
> the service was properly init()-ed, of course)? Would we require that a
> connection service user call execute() even if has no substantive result?
An argument that a particular service doesn't allow should throw
IllegalAccessException, which doesn't have to be explicitly trapped for,
(it's runtime, not compile time). This means you can be sure
application clients fix any errant calls ahead of production time, so
you don't get results (like true on execute()) that indicate something
happened when it didn't. Make sense?
>
> >
> <..snip..>
> >
> > No big deal, you still don't see, right? But what if the scheduler is
> > distributed, and on another machine? Uh.. oh... but no big deal,
> > because the client doesn't request an implementation of a _sepcific_
> > service, they request an implementation that conforms to the generic
> > _service_contract_!! This means that we can return to them an
> > XMLRPCService class, which implements Service, and give it the
> > information (in TurbineServiceManager) to know how to send the type of
> > XML-RPC that the Scheduler Engine, on another box understands. So when
> > you call execute, you aren't _really_ invoking execute() on
> > SchedulerService, but rather on XMLRPCService, that constructs an
> > XML-RPC call, sends it across the wire, and invokes execute() on
> > SchedulerService somewhere ... all unknown to the client because he is
> > using a generic Service interface, not casting to a sepcific Service
> > implementation.
> >
> Something, somewhere needs to have the intelligence to format an XML-RPC
> request for a specific service. Given the above scenario, it sounds like
> XMLRPCService has far too much knowledge about the particulars of the
> Scheduler Engine. Can you provide a more detailed description of this
> example? Here's my guess:
Not really. All XML-RPC knows about is a host to connect to. If we use
XML-RPC across the board, we can use the object passed in init() to
formulate the request to execute(). Remember this is OK, (nothing
different from non-XML-RPC) because init() would be called anyway, just
on the local caopy if it wasn't proxied via XML-RPC
>
> *) services.properties file contains an entry like:
> service.scheduler=org.apache.turbine.services.RemoteSchedulerService
No.
service.scheduler.class=org.apache.turbine.services.SchedulerService
# This can be either local (assumed if no entry) or xml-rpc
service.scheduler.communication=xml-rpc
service.scheduler.hostname=myScheduler.host.com
>
> *) RemoteSchedulerService extends the abstract class XMLRPCService, adding
> the specific knowledge required to call a Scheduler Engine residing on
> a remote host (whose URI is contained in services.properties).
No. Scheduler has absolutely _zero_ relation to XML-RPCService.
XML-RPC has some additional methods:
setHostName(String host);
setTargetClass(String className);
So when you do
TurbineServiceManager.getInstance().getService("scheduler");
TSM (TurbineServiceManager) loads up the service for scheduler, using
the props file. It gets the right class name. Then it sees what type
of communication to use. When it finds XML-RPC, it instantiates an
instance of XMLRPCService. It calls setHostName() and passes it in the
hostname from the props file. It then calls setTargetClass() and passes
in the classname for the scheduler service.
<optional>
We can either use reflection of another method to set the required
parameters for the call. The values for these parameters will be in the
object passed into init() of the service, so we can either use
reflection on that object, or give a list of accessor methods the
service() method of XML-RPC should invoke on the object to build its
request.
</optional>
Either way, the XMLRPCService creates a standard XML-RPC request that
all our services can accept; this means one XMLRPCService, generic,
services _all_ XML-RPC requests across all services. No specific code
in any services for XML-RPC, and vice versa, except for the accept()
method (that I am now adding ;-) ) to a service, which decodes an
XML-RPC request and passes it on to the right place translated from XML
to Java.
>
> *) XMLRPCService encapsulates the XML-RPC un-/marshalling required to
> call the remote procedure by declaring some abstract methods that
> provide procedure name and arguments.
Sort of... see above.
>
> Yuck, that seems ugly. What if XMLRPCService just read the procedure
> names/args from the properties file? Then you wouldn't have to create a
> new class every time you wanted to make a remote call. Okay, now I think
> I'm beginning to understand XMLRPCService.
Yes, now you are getting it. We can use this method or reflection.
Reflection is cleaner but slower. I propose we build both, and really
see it in action. This is new stuff, not being done, so let's really
see the best solution.
>
> > So this is beatiful for us ;-) We have TurbineServiceManager read in a
> > services.properties file (yes, seperate, because it may be on machines
> > that TurbineResources.properties is not), and at service request
> > (getService(serviceName)), determine whether to return the actual class
> > for a given service, or the XMLRPCClass, or a ProxyClass, or an
> > SSLRequest class, or any number of intermediary services that add
> > advanced pre- and post- processing to service behavior. All using our
> > nice simple little properties file ;-)
> >
> Maybe it's still too early, but could you give some example properties file
> entries (esp. for XMLRPCService)?
Again:
services.xmlrpc.class=org.apache.turbine.services.XMLRPCService
services.connection.class=org.apache.turbine.services.ConnectionService
# This is not needed, as it defaults to this
services.connection.communication=local
services.jndi.class=org.apache.turbine.services.JNDIService
services.scheduler.class=org.apache.turbine.services.SchedulerService
services.scheduler.communication=xml-rpc
services.scheduler.hostname=some.other.host:85
That's it. And maybe, :
services.scheduler.xmlrpc.method=eventTime=getEventTime();
services.scheduler.xmlrpc.method=eventName=getEventName();
...
Delineating both the field names and how to get the values of these
field names to build the request. These methods would be invoked on the
object passed in to the service's init() method, so all will be well ;-)
Make sense?
>
> > Examples:
> >
> > Using SchedulerService across the wire via XML-RPC...
> > Getting a URL that is SSL protected with SSLService... (lame, but an
> > example still)
> > Changing a data store from a database to LDAP without the client
> > knowing... (no casting to JNDIService vs. ConnectionService!)
> > <scott-pay-attention-here>
> > Getting a DOM layer over a SAXparser service for handling class maps if
> > one is needed.
> > </scott-pay-attention-here>
> >
> > So what do you all think?
> >
> I think you rock!
<blush />
;-)
-Brett
>
> > -Brett
> >
> >
>
> --
> Christopher Elkins
>
> ------------------------------------------------------------
> To subscribe: [EMAIL PROTECTED]
> To unsubscribe: [EMAIL PROTECTED]
> Problems?: [EMAIL PROTECTED]
------------------------------------------------------------
To subscribe: [EMAIL PROTECTED]
To unsubscribe: [EMAIL PROTECTED]
Problems?: [EMAIL PROTECTED]