Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

How to Create a Web Service using GSI Authentication and Proxy Delegation

The following is a description of how to implement and deploy an Apache-Axis based web service using the GSI Authentication/Proxy Delegation and local-interface preserving model adopted by our group.

...

Here we will focus on how to generate the service infrastructure, how to write the necessary adapter code for a specific service, and how to deploy the service.

Definitions:

IMPLEMENTATION

the Java class or classes constituting the functionality of the service

LOCAL INTERFACE

the API and data objects used by the implementation; these are exposed to other classes, but not as remote objects

REMOTE INTERFACE

the service interface generated from the local interface by Axis which exports the latter as remote objects

CLIENT ADAPTER

a service client which uses the local rather than remote interface

ENDPOINT ADAPTER

the service skeleton which also translates from the remote interface back into the local interface of the implementation

Dependencies:

We assume that the build process will be done through Eclipse, and that the user is familiar with that environment. The various phases of the build are handled by calls to the ncsa.services.build.ServiceBuilder, run, however, as a Java Application (not as a plugin).

The following Java libraries are necessary for generating the service and client. For convenience, we have wrapped them as Eclipse plugins. Not included in this list are the Eclipse, Ant, and JUnit plugins, which should be part of the standard Eclipse distribution.

External Libraries / Plugins

LIBRARY

INCLUDED IN PLUGIN

dom4j-1.5.2.jar

org.dom4j

commons-beanutils-1.7.0.jar

org.apache.commons

commons-cli-1.0.jar

org.apache.commons

commons-discovery-0.2.jar

org.apache.commons

commons-lang-2.0.jar

org.apache.commons

commons-logging-1.0.4.jar

org.apache.commons

commons-collections-3.1.jar

org.apache.commons

commons-codec-1.3.jar

org.apache.commons.codec

axis-1.2.1.jar

org.apache.axis

jaxrpc-1.1.jar

org.apache.axis

saaj-1.2.jar

org.apache.axis

log4j-1.2.7.jar

org.apache.log4j

spring-1.1.5.jar

org.spring

jmx.jar

javax.management

servlet-api.jar

javax.servlet

qname.jar

com.ibm.wsdl

wsdl4j.jar

com.ibm.wsdl

cryptix-asn-1.0.jar

org.globus.jglobus

cryptix-random-1.0.jar

org.globus.jglobus

cryptix-32-1.0.jar

org.globus.jglobus

jce-jdk13-120.jar

org.globus.jglobus

jgss-1.0.jar

org.globus.jglobus

puretls-1.0.jar

org.globus.jglobus

cog-jglobus-1.2.1

org.globus.jglobus

cog-axis.jar

cog.axis

cog-url.jar

cog.axis

NCSA plugins

NCSA PLUGIN

ncsa.tools.common

ncsa.tools.common.eclipse.descriptors

ncsa.ca.certs

ncsa.services.build

ncsa.services.client

ncsa.services.endpoint

Optional (database)

If you wish to use the service builder to do database initialization, then you will also need:

...

along with some JDBC connector, such as mysql-jdbc-3.1.7.jar.

UML

The following diagram lays out the invariant structure of a typical service. Violet class names represent external packages; blue represents ncsa.services.client or ncsa.services.endpoint abstract classes or interfaces; red represents the classes or interfaces which need to be written or generated.

...

Step-by-step instructions.

Throughout the following, we use Example to stand for the local interface class.

...

(1) Set up the plugin structure.

Create the plugins.

For the Example service, we recommend creating the following plugins:

...

Versions of the latter two can usually be copied and adapted from existing services.

Create a feature.

In addition, you will need to create a feature for building the service .war:

...

When you have finished expressing all the necessary dependencies for creating the .war file as the dependencies of the feature, select the feature.xml file in the Eclipse editor, right click (control-click) and select "PDE Tools >> Create Ant Build File" to generate all the necessary build files for the plugins in your workspace on which this feature depends.

...

(2) Create a properties file to be used by the service builder.

The following template can be used. Replace the following references appropriately:

...

service.name=${name}
wsdl.name=${pname}.wsdl
package.dir=${package}/service
endpoint.package=${package}.service.endpoint
client.plugin.path=${eclipse}/${package}.client
endpoint.plugin.path=${eclipse}/${package}.endpoint
wstypes.plugin.path=${eclipse}/${package}.wstypes
feature.build.path=${eclipse}/${package}.feature
war.path=${war.dir}/${pname}.war
build.dir=${eclipse}/ncsa.services.build/${package}
deploy.dir=${eclipse}/${package}.endpoint/deploy
server.config.path=${eclipse}/${package}.endpoint/deploy/WEB-INF/server-config.wsdd
impl.interface=Example
default.url=httpg://localhost:8443/${pname}/services/${name}
style=WRAPPED
namespace=urn:service.${urnpackage}
scope=application
verbose=true
includeStub=false
types.namespace=types.service.${urnpackage}
types.packages=

hibernate.mappings.root=${eclipse}/${package}.impl/resources/mappings
hibernate.delimiter=:
hibernate.properties.file=${eclipse}/${package}.endpoint/deploy/WEB-INF/classes/datasource.properties
hibernate.output.file=${eclipse}/ncsa.services.build/schemas/${pname}.sql
hibernate.quiet=false
hibernate.text.only=false
hibernate.drop=false
hibernate.create=true

Notes
  1. The settings above are for generating wrapped (document-literal) wsdl from the local interface.
  2. The packages of all data types referenced by Example should be included under types.packages using a comma-separated list (no spaces); these will all be mapped by the wsdl generator to the indicated types.namespace.

...

Place this properties file in some convenient local directory.

...

(3) Create the service infrastructure.

Inside of Eclipse, select "Run", choosing the ncsa.services.build.ServiceBuilder from the ncsa.services.build plugin you have installed. Set the command-line arguments to:

...

The extension point is declared in the ncsa.services.client plugin; the extensions should be declared in the wstypes plugin where they reside.

...

(4) Implement the specific service-layer endpoints.

This is the coding phase of the build; in essence, the connecting code between LOCAL --> REMOTE (client) and REMOTE --> LOCAL (endpoint) needs to be developed.

...

  1. Convert local to remote or remote to local objects (using a utility class);
  2. Invoke the analogous method on the delegate class.
Object conversion.

Axis has trouble with Java Collection and Map types, so objects destined to go over the wire should substitute arrays for these.

Given the exclusion of such untyped containers along with the fact that wstypes are merely cloned classes with a different package name, conversion from local to remote object and back can be handled entirely by reflection. This is done via the ncsa.tools.common.utils.bean.ImplicitBeanConverter.

Endpoint Adapter.

This class should extend the ncsa.services.endpoint.GSIDelegatingEndpoint class and implement the remote service interface (i.e., the wstypes interface generated from the local interface). For each method of the remote interface, it should convert any special data types (i.e., those in the wstypes plugin) to their local variants, and then use those to call the corresponding method on the class implementing the local interface. Outgoing return objects or specialized exceptions need to be converted back to their wire equivalents.

...

Note how no conversion is necessary in the case of the second method, since all types belong to java.lang.

Security Context Information

As mentioned above, the base class stores the proxy in the in-memory repository. This happens via the call to extractAuthorizationInfo, which does the following:

...

Should you wish to replace this storage mechanism with something else, then the new class should be substituted for the MemoryAuthenticationRepository in the bean definition; this class must implement ncsa.services.endpoint.security.IAuthenticationRepository. (Notice also how the endpoint example above uses the Spring context to retrieve its implementation.)

Client Adapter.

This class should extend the ncsa.services.client.GSIServiceClientAdapter class and implement the local interface. For each method of the local interface, it should convert any special types corresponding to those in the wstypes plugin to those remote variants, and then use those to call the superclass invoke method. Any return objects or specialized exceptions need to be converted back to their local equivalents.

...

  1. getWSDLName is the name of the wsdl resource placed in the client .jar. This is used in order to initialize the base class (via a special WSDL helper class).
  2. getBundle should return the OSGI (Eclipse) bundle for the client (this is necessary for running the client as a plugin).

...

(5) Build the service .war.

Inside of Eclipse, select "Run", choosing the ncsa.services.build.ServiceBuilder from the ncsa.services.build plugin you have installed. Set the command-line arguments to:

...

This will build the .war file and place it in the location you indicated in the properties file.

NOTE

The JGlobus dependencies listed below should be placed in ${CATALINA_HOME}/common/lib, not in the individual service wars:

LIBRARY

INCLUDED IN PLUGIN

cryptix-asn-1.0.jar

org.globus.jglobus

cryptix-random-1.0.jar

org.globus.jglobus

cryptix-32-1.0.jar

org.globus.jglobus

jce-jdk13-120.jar

org.globus.jglobus

jgss-1.0.jar

org.globus.jglobus

puretls-1.0.jar

org.globus.jglobus

cog-jglobus-1.2.1

org.globus.jglobus

...

(6) Initialize the database (optional).

Most of the services we work with maintain state via a database. We have generally adopted the Spring/Hibernate mechanism for persisting Java objects to them.

...