BeNOW Service API
Andrew Taylor <andy@benow.ca>
Usage
- Design
- Implement
- Register
- Provide
- Invoke
HttpService
WebService
Javadoc
The Service API facilitates design, exposure and remote and local invocation of grouped like tasks (methods of the service).


Usage
In brief, these are the steps for using the service api:

1) Design the service interface. The service interface declares like grouped methods that process input and return a result. The interface is a normal java interface, but with Annotations that further document the service and its methods. The annotations in the service will be used during provision. The service must extend the Service interface and the class and all methods to expose require the Publish annotation. An example service interface is the TestService:

2) Implement the service interface. Create an implementation for the service interface which does the actual processing. The implementation does not need the service annotations, as the service interface is used for parameter processing. An example implementation is TestServiceImpl:

3) Register the service. Once services have been created and implemented, LocalServices is run as an application which searches class files for Service interfaces and implementations. The names of these classes are stored in a file, which is bundled as a resource (in a standard location) in the output jar. When LocalServices starts up, it scans all jars on the classpath for the service resource file and loads the services and implementations. So, with jars containing registered services, the only action required to use the services is to add the jar to the classpath and the services will be automatically discovered.

The easiest way to register services is by scanning for them before building the project jar via ant. The following snippet shows how to scan and register services before packaging the jar:

<target name="jar" depends="compile" description="Create binary distribution">

  <!-- scan classes and register services -->
  <java classname="org.benow.service.ServiceRegistrar" failonerror="true" fork="true">
    <classpath>
      <path refid="compile.classpath"/>
      <pathelement location="${java.home}/lib/rt.jar"/>
    </classpath>
  </java>

  <!-- package jar including services -->
  <jar jarfile="${app.name}.jar">
    <fileset dir="${build.home}"/>
    <fileset file="etc/services"/>
  </jar>

</target>

That snippet registered only services. If you have other operations to do during the scan, they can be chained together. The following snippet registers services and creates xml (and other) mappings (a part of the benow-castor api), then packages the jar:
<target name="jar" depends="compile" description="Create binary distribution">

  <!-- scan classes and register services and mapping -->
  <java classname="org.benow.java.cls.ClassScanner" failonerror="true" fork="true">
    <classpath>
      <path refid="compile.classpath"/>
      <pathelement location="${java.home}/lib/rt.jar"/>
    </classpath>
    <arg value="--handlers"/>
    <arg value="ca.reachable.mapping.MappingRegistrar,org.benow.service.ServiceRegistrar"/>
  </java>

  <!-- package jar including services and mapping -->
  <jar jarfile="${app.name}.jar">
    <fileset dir="${build.home}"/>
    <fileset dir="etc/castor"/>
    <fileset file="etc/services"/>
  </jar>

</target>

Once the service mapping file has been created it must be packaged into the jar. The following ant snippet includes the services file when making the jar:


, the local services can load it directly from the classpath at startup. Service discovery doesn't get much easier.

4) Provide LocalServices is available for local execution only, which is not terribly useful in a distributed processing environment. Service publishers may be designed to expose LocalServices and service requests to remote clients. The primary implementation of a service publisher is the HttpService, which is a servlet that reads requests, translates and invokes and delivers the result. It speaks via standard http multi-part post params, which makes it very easy to debug. The service publishers automatically make available all known (and published) services and implementations.

5) Invoke Via the RemoteServices class, the service (by interface or directly by implementation class) is requested from the remote service provider using a ServiceConnection which corresponds to the way the service is published (ie HttpService). The client knows how to talk to the publisher, so it is able to translate from method requests to the over-the-wire protocol (ie http multi-part post params). However, the specification of what method on what service with what params is to be called is awkward when specified directly, so RemoteServices performs a bit of funky voodoo. First, the client (that is making the request of the server) knows of the requested service interface and dynamically creates a translator which implements the service interface. This translator invokes the remote method invocator (on the ServiceConnection) with the parameters specified at execution and the connection sends the remote invocation request across the network connection. The remote application then makes requests to the translator (which implements the given service), tho they are working at the interface level and have no idea of the translation at all.

The end result is that the parameters are passed, the remote method is called and the result is returned. All of the complexity of request translation and internal protocol is hidden from the casual api user... as far as they are concerned, they just request a service, execute a method and do something with the result, like this:

This snippet gets the remote services (using http to communicate), takes a TestService, executes the echo method and displays the result. Very simple, considering what is happening behind the scenes.


HttpService
The initial implementation of the service provider, the HttpService (aka http provider), is intended to be the primary way of remote access to services. The http provider also has several key features:
  • Secure - SSL security is planned, which makes evesdropping on requests and logins impossible.
  • Authenticated - Much like a web application, users can be associated with repeated processing. The permissions which determine what a user can and cannot do is defined on the server (via the BeNOW Security and Web APIs)
  • Standard - the use of standard http multi-part post params for service invocation means that testing services and remote invocation itself is as easy as opening a web browser. All security and authentication conforms to what a web browser expects. The http service client essentially bundles up and sends requests in a format identical to that of a web browser.
What is uncertain is whether the http service communications method will be fast enough for heavy duty processing. There are many tricks to speeding up http connections, so it might be possible to tune it if it is not fast enough initially.


WebService
Furthermore, the LocalServices is intended to be used locally in conjunction with the web api to enable fast exposure of server features and fast page prototyping and design. More on the web-service integration can be found in the web technical documentation.

It is a large beast, this service api, and is not yet completed. It does have many advantages and few disadvantages over alternative methods. Once debugged, it should be a breeze to use and re-use.


Javadoc
Javadocs can be built via 'ant javadoc'. Once built, they may be viewed here.