Difference between revisions of "Single Port-Type"

From GCube System
Jump to: navigation, search
(Sketching Port-type Interfaces: filling the holes)
(Delving into the implementation)
Line 137: Line 137:
 
== Delving into the implementation ==
 
== Delving into the implementation ==
  
=== Service Context ===  
+
=== The Service Context ===  
 +
The fist thing to implement is the Service Context. It is a static component which represents the whole service within the GHN and the rest of its implementation.
 +
It has multi-fold role:
 +
* a provider of service-wide information & utilities
 +
* bootstraps the service within the GHN
 +
* gives access to JNDI configuration & profile information
 +
* manages security and scope
 +
* …and more
 +
The role of the service context it's very complex role, but fortunately it’s all transparently catered for by the gCore Framework. What is needed it's just derive your context it from ''GCUBEServiceContext'' class and fill in the blanks.
  
 +
Create a ServiceContext.java class in your SERVICE source root folder.
 +
<pre>
 +
package org.acme.sample;
 +
 +
import org.gcube.common.core.contexts.GCUBEServiceContext;
 +
 +
public class ServiceContext extends GCUBEServiceContext {
 +
 +
 +
/** Single context instance, created eagerly */
 +
private static ServiceContext cache = new ServiceContext();
 +
 +
/** Returns cached instance */
 +
public static ServiceContext getContext() {return cache;}
 +
 +
/** Prevents accidental creation of more instances */
 +
private ServiceContext(){};
 +
 +
/**
 +
* {@inheritDoc}
 +
*/
 +
public String getJNDIName() {return "acme/sample";}
 +
 +
}
 +
</pre>
 +
 +
Comments:
 +
 +
* the class adopts the singleton pattern. As best practice it is strongly suggested to always adopt it for ANY context defined in a gCube service
 +
* the getJNDIName() method identifies the configuration in the JNDI file and must return the name given to the service there. It MUST be implemented
  
 
=== A first implementation for the Stateless Port-Type ===
 
=== A first implementation for the Stateless Port-Type ===
 +
 +
 +
=== Towards Deployment: the WSDD descriptor ===
  
 
== Building & Deploying ==
 
== Building & Deploying ==

Revision as of 00:10, 22 March 2008

From configuration to testing with a single Port-Type

Even if not compulsory, we strongly suggest to adopt the Eclipse 3.3 as development platform. In such an IDE, open a new workspace with a Java 1.5 compiler and create a new Java project by specifying a source folder (named from now on, SERVICE folder). Then, fill a user-library with all JARs in gCore lib and name it CONTAINERLIB.

Structuring the service code

Prepare the source folder structure as follows:

  1. create a etc folder where to place your configuration files
  2. create a org/acme/sample folder where to place your source code
  3. create a schema folder where to place the remote interface files
  4. copy the share/gcube_tools/build.xml file into your SERVICE folder

Profiling for the infrastructure

Create a new XML file named Profile.xml and place it in the SERVICE/etc folder. This file profiles the service in such a way that the instance of a service can be discovered by others and eventually dynamically deployed in a gCube infrastructure.

<Resource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<ID></ID>
	<Type>Service</Type>
	<Profile>
		<Description>A very simple gCube Service</Description>
		<Class>Samples</Class>
		<Name>SampleService</Name>
		<Packages>
			<Main>
				<Description>Describes port-types</Description>
				<Name>Main</Name>
				<Dependencies>
					<Dependency>
						<Service>
							<Class>Samples</Class>
							<Name>SampleService</Name>
						</Service>
						<Package>Stubs</Package>
						<Version>1.0</Version>
						<Scope level="GHN"/>
						<Optional>false</Optional>
					</Dependency>
				</Dependencies>
				<GARArchive>org.acme.sample.gar</GARArchive>
				<PortType>
					<Name>acme/sample/stateless</Name>
					<WSDL/>
				</PortType>
			</Main>
			<Software>
				<Description>Describes port-type stubs</Description>
				<Name>Stubs</Name>
				<Files><File>org.acme.sample.stubs.jar</File></Files>
			</Software>
		</Packages>
	</Profile>
</Resource>

The file identifies our service by assigning it a ServiceClass and a ServiceName. It also describes the service decomposition: it is composed by two packages, the service itself and its stubs and that the first one has a GHN-scoped dependency against the second one. Finally, it indicates that the service has a single Port-Type named acme/sample/stateless.

JNDI configuration

Create a new XML file named deploy-jndi-config.xml and and place it in the SERVICE/etc folder. It will include either the global service configuration and the all the Port-Type ones. The file has a two-fold role:

  1. tells to the gCube framework about the service
  2. makes available to the service at runtime the information included there
<jndiConfig xmlns="http://wsrf.globus.org/jndi/config">
	<service name="acme/sample">
	
		<environment 
		name="profile" 
	 	value="@config.dir@/profile.xml" 
	 	type="java.lang.String"
	 	override="false" />
		 	
	</service>
</jndiConfig>

At this stage, the file only include a service section reporting the name of the service ("acme/sample") and the name of the profile created. The @config.dir@ is a placeholder replaced at the deployment time with the real path of the SERVICE/etc folder.

Sketching Port-type Interfaces: WSDL structure

The following is the basic skeleton of any WSDL interface:

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:tns="...." xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
name="Stateless" targetNamespace=".....">
	<types>
		<xsd:schema targetNamespace=".....">
			<!-- REQUEST AND RESPONS TYPE DEFINITIONS -->
		</xsd:schema>
	</types>
	
	<!-- MESSAGES  -->

	<portType name=".....">

		<!-- OPERATION -->

	</portType>
</definitions>

Sketching Port-type Interfaces: the Stateless Port-Type

Create a new WSDL file, name it Stateless.wsdl and place the file in the SERVICE/etc folder.

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:tns="http://acme.org/sample" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:corefaults="http://gcube-system.org/namespaces/common/core/faults" name="Stateless" targetNamespace="http://acme.org/sample">
	<import namespace="http://gcube-system.org/namespaces/common/core/faults" location="../gcube/common/core/faults/GCUBEFaults.wsdl"/>
	<types>
		<xsd:schema targetNamespace="http://acme.org/sample">
			<xsd:element name="about" type="xsd:string"/>
			<xsd:element name="aboutResponse" type="xsd:string"/>
		</xsd:schema>
	</types>
	<message name="aboutInputMessage">
		<part name="request" element="tns:about"/>
	</message>
	<message name="aboutOutputMessage">
		<part name="response" element="tns:aboutResponse"/>
	</message>
	<portType name="StatelessPortType">
		<operation name="about">
			<input message="tns:aboutInputMessage"/>
			<output message="tns:aboutOutputMessage"/>
			<fault name="fault" message="corefaults:GCUBEUnrecoverableFaultMessage"/>
			<fault name="fault" message="corefaults:GCUBERetrySameFaultMessage"/>
			<fault name="fault" message="corefaults:GCUBERetryEquivalentFaultMessage"/>
		</operation>
	</portType>
</definitions>

This file defines the interface of the first stateless Port-Type of the Sample Service. The interface has a single operation, named about that accepts as input a string and returns a string as output. Moreover, the operation can throw three types of fault, that are defined in the imported GCUBEFaults.wsdl. Each fault has a specific semantic within a gCube infrastructure:

  • GCUBEUnrecoverableFaultMessage ...
  • GCUBERetrySameFaultMessage...
  • GCUBERetryEquivalentFaultMessage ...

Delving into the implementation

The Service Context

The fist thing to implement is the Service Context. It is a static component which represents the whole service within the GHN and the rest of its implementation. It has multi-fold role:

  • a provider of service-wide information & utilities
  • bootstraps the service within the GHN
  • gives access to JNDI configuration & profile information
  • manages security and scope
  • …and more

The role of the service context it's very complex role, but fortunately it’s all transparently catered for by the gCore Framework. What is needed it's just derive your context it from GCUBEServiceContext class and fill in the blanks.

Create a ServiceContext.java class in your SERVICE source root folder.

package org.acme.sample;

import org.gcube.common.core.contexts.GCUBEServiceContext;

public class ServiceContext extends GCUBEServiceContext {

	
	/** Single context instance, created eagerly */
	private static ServiceContext cache = new ServiceContext();
	
	/** Returns cached instance */
	public static ServiceContext getContext() {return cache;}
	
	/** Prevents accidental creation of more instances */
	private ServiceContext(){};
		
	/**
	 * {@inheritDoc}
	 */
	public String getJNDIName() {return "acme/sample";}
	
}

Comments:

  • the class adopts the singleton pattern. As best practice it is strongly suggested to always adopt it for ANY context defined in a gCube service
  • the getJNDIName() method identifies the configuration in the JNDI file and must return the name given to the service there. It MUST be implemented

A first implementation for the Stateless Port-Type

Towards Deployment: the WSDD descriptor

Building & Deploying

gCore Logging & Restart

A Test Client

Refining the implementation