Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "COSMOS DG Constructing a Data Manager"

(Replacing page with 'COSMOS Wiki > COSMOS Document Plan > COSMOS Manual Guide The most current content for this documentation is f...')
 
Line 1: Line 1:
 
[[COSMOS|COSMOS Wiki]] > [[COSMOS_Documentation_Plan|COSMOS Document Plan]] > [[COSMOS_Manual_Guide |COSMOS Manual Guide]]
 
[[COSMOS|COSMOS Wiki]] > [[COSMOS_Documentation_Plan|COSMOS Document Plan]] > [[COSMOS_Manual_Guide |COSMOS Manual Guide]]
  
== COSMOS Development Guide Constructing a Data Manager ==
+
The most current content for this documentation is found here: http://www.eclipse.org/cosmos/documents/v1.0/devguide/cosmosdevguide04.htm#HDRDQX1CREATINGADATAMANAGER
 
+
Category: [http://wiki.eclipse.org/Category:COSMOS_Development_Guide Development Guide]
+
+
{| border="1" cellpadding="2"
+
|-
+
|'''Owner'''
+
|
+
* Hubert Leung
+
* Ali Mehregani
+
* David Whiteman
+
 
+
|-
+
|'''Bug #'''
+
|[https://bugs.eclipse.org/bugs/show_bug.cgi?id=219141 219141]/ [https://bugs.eclipse.org/bugs/show_bug.cgi?id=219142 219142]
+
 
+
|-
+
|'''Due dates'''
+
| [[COSMOS_Document_Schedule#COSMOS Development Guide| Schedule]]
+
|}
+
 
+
== Outline ==
+
 
+
= Introduction =
+
 
+
Learning a new framework or toolkit can be a daunting task.  For most of us, such things are best accomplished by example.  In this section, we will walk you through the process of building a sample Management Data Repository (MDR) using the COSMOS SDK.  In the process, we hope to help you accomplish the following goals:
+
 
+
* Setting up your development environment for building Management Data Repositories (MDRs)
+
* Becoming familiar with the tools included with the COSMOS SDK
+
* Becoming familiar with the underlying framework and APIs that enable you to build MDRs for your existing data store
+
* Building a working example that shows techniques and best practices for building a CMDBf query service
+
* Understanding the concepts presented by both COSMOS and CMDBf
+
 
+
The sample MDR you will build contains data for a hypothetical school.  This data includes students, teachers, courses, and their relationships.  For the duration of this section, we will refer to this sample as the Student-Teacher sample.
+
 
+
To keep things simple, we have provided a sample repository consisting of XML files.  While this does not represent a typical production data store, the techniques learned in using the COSMOS framework and tools can be applied to other data stores such as relational databases. 
+
 
+
There are also several other example MDRs provided with COSMOS.  These examples show how to implement query and registration services with different types of data stores, and with different optional features.  They can be downloaded as part of the ??? package on the COSMOS web site.
+
 
+
= Setting up the Development Environment =
+
 
+
COSMOS provides a set of tools to help you build an MDR.  These tools are provided as extensions to the Eclipse SDK environment.  They are included as part of the COSMOS SDK package.
+
 
+
To begin building the MDR in this Student-Teacher example, you must first install the COSMOS SDK into Eclipse.  There are a number of prerequisites for the COSMOS SDK, including Eclipse Webtools and its prerequisites.  Please refer to the [[COSMOS_InstallGuide10|COSMOS Installation Guide]] for specifics on how to install the COSMOS SDK and its prerequisites.
+
 
+
= Creating the Student-Teacher Project =
+
 
+
Follow the instructions below to create an MDR project for the Student-Teacher sample:
+
 
+
# Click <b> File > New > Project </b>
+
# Expand <b> Web </b> and select <b> Dynamic Web Project </b>
+
# Click <b>Next</b> and type in <b>org.eclipse.cosmos.example.mdr</b> as the project name
+
# In the Target Runtime field, select the Apache Tomcat server where you want to deploy the data manager project. If a Tomcat server is not already defined, click <b>New...</b> to select a server runtime environment.
+
# After you define and select a target runtime for Apache Tomcat, the configuration "Default Configuration for Apache Tomcat v5.5" will be available for selection. Follow the steps below to configure the project:
+
## Select the configuration and click the <b>Modify...</b> button. The Project Facets dialog will open.
+
## Select the <b>Axis2 Web Services</b> facet category. Axis2 is the web services implementation used by COSMOS to deploy MDRs to a J2EE container.
+
## Under the <b>Systems Management</b> category, select <b>CMDBf query service</b> to implement an MDR with a query service.  For the purpose of the Teacher-Student sample we will not need the registration service.  Any MDR intending to provide a CMDBf registration service would also select the second option under <b>System Management</b>.
+
## Press OK to complete the configuration.
+
# Click <b>Next</b> twice to skip to the <b>MDR Configuration</b> page
+
# Enter <b>org.eclipse.cosmos.example.mdr</b> as the package name and <b>StudentTeacherSample</b> as the MDR name
+
# Click <b>Finish</b> to create the project
+
 
+
= Configuring the Student-Teacher Project =
+
 
+
Follow the instructions below to configure the project created in the previous section:
+
 
+
# Right click the project and select <b>Properties</b>
+
# Select <b>Java Build Path</b> on the left panel
+
# Select the <b>Libraries</b> tab
+
# Click <b>Add Variable...</b>, select <b>ECLIPSE_HOME - ...</b> and click on <b>Extend...</b>
+
# Expand <b>plugins</b> and select <b>org.eclipse.osgi_<<suffix>></b>
+
# Click <b>OK</b> to close the variables dialog
+
# Click <b>OK</b> to close the properties dialog
+
 
+
= The Student-Teacher Repository =
+
 
+
This section will include code for implementing a simple XML-based repository.  The content of the repository is contained in an XML file that is processed using a SAX parser.  The implementation consists only of two Java classes: a file used to represent the entities of the XML content, and a SAX parser used to load in the XML content into memory.
+
 
+
Before implementing the Java classes, create a file called <b>data.xml</b> under org.eclipse.cosmos.example.mdr/src.  The content of the file appears below:
+
 
+
<pre>
+
<?xml version="1.0" encoding="UTF-8"?>
+
<school>
+
<student>
+
<identity firstName="Bob" lastName="Davidson" id="01"/>
+
</student>
+
+
<student>
+
<identity firstName="Jane" lastName="Ryerson" id="02"/>
+
</student>
+
+
<student>
+
<identity firstName="Mike" lastName="Lee" id="03"/>
+
</student>
+
+
<teacher>
+
<identity firstName="Dawn" lastName="Johnson" id="staff01"/>
+
</teacher>
+
+
<teacher>
+
<identity firstName="Heather" lastName="Reeba" id="staff02"/>
+
</teacher>
+
+
<class name="Economics" courseCode="ECM01">
+
<students>
+
  <enrolledStudent idRef="01"/>
+
  <enrolledStudent idRef="03"/>
+
</students>
+
<teacher idRef="staff01"/>
+
</class>
+
+
<class name="Mathematics" courseCode="MAT01">
+
<students>
+
  <enrolledStudent idRef="01"/>
+
  <enrolledStudent idRef="02"/>
+
</students>
+
<teacher idRef="staff02"/>
+
</class>
+
+
<class name="Physics" courseCode="PHY01">
+
<students>
+
  <enrolledStudent idRef="02"/>
+
  <enrolledStudent idRef="03"/>
+
</students>
+
<teacher idRef="staff02"/>
+
</class>
+
</school>
+
</pre>
+
 
+
Notice the file contains three students, two teachers, and three classes.  Each student and teacher element defines a unique ID using the 'id' attribute and each class indicates the teacher and the enrolled students using the id field.
+
 
+
 
+
Let's now create the classes that will load in the data above.  Create the following two classes under src/org.eclipse.cosmos.example.mdr.handlers:
+
 
+
# XMLRepository
+
# SchoolXMLHandler
+
 
+
The first file provides an object representation of the entities in data.xml (i.e. student, teacher, and class).  The content of <b>XMLRepository</b> appears below:
+
 
+
<pre>
+
package org.eclipse.cosmos.example.mdr.handlers;
+
 
+
import java.io.IOException;
+
import java.io.StringWriter;
+
 
+
import javax.xml.parsers.ParserConfigurationException;
+
import javax.xml.parsers.SAXParserFactory;
+
 
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.common.CMDBfServicesUtil;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.common.IXMLWritable;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.transform.response.artifacts.IItemConvertible;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.transform.response.artifacts.INodes;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.transform.response.artifacts.IRelationshipConvertible;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.transform.response.artifacts.QueryOutputArtifactFactory;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.transform.artifacts.IGraphElement;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.transform.artifacts.IGraphElementCollection;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.transform.artifacts.IItem;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.transform.artifacts.IRecord;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.transform.artifacts.IRelationship;
+
import org.xml.sax.SAXException;
+
 
+
/**
+
* This class represents a simple repository that is populated
+
* by the data stored in a static XML file.  An implementation of
+
* IDataProvider is used to provide a binding to an underlying
+
* repository.
+
*/
+
public class XMLRepository
+
{
+
/**
+
* The MDR ID
+
*/
+
public static final String MDR_ID = "org.eclipse.cosmos.samples.cmdbf.XMLRepository";
+
+
/**
+
* The XML file that stores the data
+
*/
+
private static final String XML_DATA = "data.xml";
+
+
/**
+
* The namespace of the data
+
*/
+
private static final String SCHOOL_NAMESPACE = "http://school";
+
+
/**
+
* The students of the school
+
*/
+
public Student[] students;
+
+
/**
+
* The teachers of the school
+
*/
+
public Teacher[] teachers;
+
+
/**
+
* The classes of the school
+
*/
+
public ClassSession[] classes;
+
+
+
/**
+
* Constructor
+
*
+
* @throws ParserConfigurationException
+
* @throws IOException
+
* @throws SAXException
+
*/
+
public XMLRepository() throws ParserConfigurationException, SAXException, IOException
+
{
+
// Read in the XML file and populate fields accordingly
+
SchoolXMLHandler schoolXMLHandler = new SchoolXMLHandler();
+
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
+
saxParserFactory.newSAXParser().parse(XMLRepository.class.getClassLoader().getResourceAsStream(XML_DATA), schoolXMLHandler);
+
+
students = schoolXMLHandler.getStudents();
+
teachers = schoolXMLHandler.getTeachers();
+
classes = schoolXMLHandler.getSchoolClasses();
+
}
+
+
+
/**
+
* Represents an identity, which is consisted
+
* of a first name, last name, and an id.
+
*/
+
public static class Identity
+
{
+
public String firstName;
+
public String lastName;
+
public String id;
+
}
+
+
/**
+
* An abstract class representing a school
+
* member
+
*/
+
public abstract static class SchoolMember implements IItemConvertible, IXMLWritable
+
{
+
public Identity identity = new Identity();
+
+
public IItem toItem(INodes parent)
+
{
+
IItem item = QueryOutputArtifactFactory.getInstance().createItem();
+
item.addInstanceId(QueryOutputArtifactFactory.getInstance().createInstanceId(MDR_ID, identity.id));
+
IRecord record = QueryOutputArtifactFactory.getInstance().createRecord(item, identity.id);
+
record.addNamespace("", SCHOOL_NAMESPACE);
+
record.setValue(this);
+
item.addRecord(record);
+
return item;
+
}
+
+
private static String valueWithIndent(int indent, String value)
+
{
+
String tempValue = value;
+
StringWriter tabsWriter = new StringWriter();
+
tabsWriter.append('\n');
+
CMDBfServicesUtil.addIndent(tabsWriter, indent);
+
tempValue = tempValue.replace("\n", tabsWriter.toString());
+
tempValue = tabsWriter.toString() + tempValue;
+
return tempValue;
+
}
+
+
public void toXML(StringWriter writer, int indentLevel)
+
{
+
StringBuffer buffer = new StringBuffer();
+
buffer.append ("<" + getElementName() + ">\n");
+
buffer.append (" <identity firstName=\"" + identity.firstName + "\" lastName=\"" + identity.lastName + "\" id=\"" + identity.id + "\"/>\n");
+
buffer.append ("</" + getElementName() + ">");
+
writer.write(SchoolMember.valueWithIndent(indentLevel, buffer.toString()) + "\n\n");
+
}
+
 
+
protected abstract String getElementName();
+
}
+
+
/**
+
* Represents a student
+
*/
+
public static class Student extends SchoolMember
+
{
+
@Override
+
protected String getElementName()
+
{
+
return "student";
+
}
+
 
+
}
+
+
/**
+
* Represents a teacher of a school
+
*/
+
public static class Teacher extends SchoolMember
+
{
+
@Override
+
protected String getElementName()
+
{
+
return "teacher";
+
}
+
}
+
+
/**
+
* Represents a class with enrolled students
+
* and a teacher
+
*/
+
public static class ClassSession implements IItemConvertible, IRelationshipConvertible, IXMLWritable
+
{
+
public Student[] students;
+
public Teacher teacher;
+
public String name;
+
public String courseCode;
+
public IItem toItem(INodes parent)
+
{
+
IItem item = QueryOutputArtifactFactory.getInstance().createItem();
+
item.addRecord(createRecord(item));
+
return item;
+
}
+
+
+
public IRelationship toRelationship(IGraphElementCollection parent)
+
{
+
IRelationship relationship = QueryOutputArtifactFactory.getInstance().createRelationship();
+
relationship.addInstanceId(QueryOutputArtifactFactory.getInstance().createInstanceId(MDR_ID, courseCode));
+
relationship.addRecord(createRecord(relationship));
+
return relationship;
+
}
+
+
private IRecord createRecord(IGraphElement parent)
+
{
+
IRecord record = QueryOutputArtifactFactory.getInstance().createRecord(parent, courseCode);
+
record.addNamespace("", SCHOOL_NAMESPACE);
+
record.setValue(this);
+
return record;
+
}
+
 
+
 
+
public void toXML(StringWriter writer, int indentLevel)
+
{
+
StringBuffer buffer = new StringBuffer();
+
buffer.append("<class name=\"" + name + "\" courseCode=\"" + courseCode + "\">\n");
+
buffer.append(" <students>\n");
+
for (int i = 0; i < students.length; i++)
+
{
+
buffer.append("  <enrolledStudent idRef=\"" + students[i].identity.id + "\"/>\n");
+
}
+
buffer.append(" </students>\n");
+
buffer.append(" <teacher idRef=\"" + teacher.identity.id + "\"/>\n");
+
buffer.append("</class>");
+
+
writer.write(SchoolMember.valueWithIndent(indentLevel, buffer.toString()) + "\n\n");
+
}
+
}
+
}
+
</pre>
+
 
+
The second file is a SAX handler required for loading data.xml into memory.  The content of <b>SchoolXMLHandler</b> appears below:
+
 
+
<pre>
+
package org.eclipse.cosmos.example.mdr.handlers;
+
 
+
import java.util.ArrayList;
+
import java.util.Hashtable;
+
import java.util.List;
+
import java.util.Map;
+
 
+
import org.eclipse.cosmos.example.mdr.handlers.XMLRepository.ClassSession;
+
import org.eclipse.cosmos.example.mdr.handlers.XMLRepository.Identity;
+
import org.eclipse.cosmos.example.mdr.handlers.XMLRepository.Student;
+
import org.eclipse.cosmos.example.mdr.handlers.XMLRepository.Teacher;
+
import org.xml.sax.Attributes;
+
import org.xml.sax.SAXException;
+
import org.xml.sax.helpers.DefaultHandler;
+
 
+
/**
+
* The XML handler for parsing the data that represents
+
* a school with students, teacher, and classes
+
*/
+
public class SchoolXMLHandler extends DefaultHandler
+
{
+
private Student currentStudent;
+
private Teacher currentTeacher;
+
private ClassSession currentClass;
+
private List<Student> enrolledStudents;
+
+
private Map<String, Student> students;
+
private Map<String, Teacher> teachers;
+
private List<ClassSession> classes;
+
+
public SchoolXMLHandler()
+
{
+
students = new Hashtable<String, Student>();
+
teachers = new Hashtable<String, Teacher>();
+
classes = new ArrayList<ClassSession>();
+
enrolledStudents = new ArrayList<Student>();
+
}
+
+
@Override
+
public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException
+
{
+
if ("student".equals(name))
+
{
+
currentStudent = new Student();
+
}
+
else if ("teacher".equals(name) && currentClass == null)
+
{
+
currentTeacher = new Teacher();
+
}
+
else if ("class".equals(name))
+
{
+
currentClass = new ClassSession();
+
currentClass.name = attributes.getValue("name");
+
currentClass.courseCode = attributes.getValue("courseCode");
+
}
+
else if ("identity".equals(name))
+
{
+
Identity identity = currentStudent != null ?
+
currentStudent.identity : currentTeacher.identity;
+
+
identity.firstName = attributes.getValue("firstName");
+
identity.lastName = attributes.getValue("lastName");
+
identity.id = attributes.getValue("id");
+
}
+
else if ("enrolledStudent".equals(name))
+
{
+
enrolledStudents.add(students.get(attributes.getValue("idRef")));
+
}
+
else if ("teacher".equals(name))
+
{
+
currentClass.teacher = teachers.get(attributes.getValue("idRef"));
+
}
+
+
}
+
+
@Override
+
public void endElement(String uri, String localName, String name) throws SAXException
+
{
+
if ("student".equals(name))
+
{
+
students.put(currentStudent.identity.id, currentStudent);
+
currentStudent = null;
+
}
+
else if ("teacher".equals(name) && currentClass == null)
+
{
+
teachers.put(currentTeacher.identity.id, currentTeacher);
+
currentTeacher = null;
+
}
+
else if ("class".equals(name))
+
{
+
currentClass.students = enrolledStudents.toArray(new Student[enrolledStudents.size()]);
+
classes.add (currentClass);
+
currentClass = null;
+
enrolledStudents.clear();
+
}
+
}
+
+
public Student[] getStudents()
+
{
+
return students.values().toArray(new Student[students.size()]);
+
}
+
+
public Teacher[] getTeachers()
+
{
+
return teachers.values().toArray(new Teacher[teachers.size()]);
+
}
+
+
public ClassSession[] getSchoolClasses()
+
{
+
return classes.toArray(new ClassSession[classes.size()]);
+
}
+
}
+
</pre>
+
 
+
This concludes implementing the simple XML repository.  The next section will describe how the repository can be extended to provide CMDBf query support.
+
 
+
= Providing CMDBf Query Support =
+
 
+
As described in the previous section, the [http://www.cmdbf.org CMDBf specification] defines a query and a registration service.  COSMOS provides a set of reusable, extensible classes and interfaces that can be utilized in implementing such services.  This section will cover how COSMOS APIs can be used in providing a CMDBf query implementation for the Student-Teacher example.
+
 
+
 
+
== Architecture ==
+
 
+
The process of handling a CMDBf query involves traversing a structure representing the request, processing each individual part, and generating a structure representing the result.  COSMOS has already defined structures representing the request and response.  There is also generic code in place for traversing the request and invoking handlers for individual part of the CMDBf request.  A consumer needs to only provide implementation of such handlers as part of implementing the query service.
+
 
+
A handler is required to process each CMDBf query constraint that an implementation supports.  In addition to constraint handlers, the framework also requires two handlers for item templates and relationship templates.  Here's the order in which the handlers are invoked:
+
 
+
# Item/Relationship template handler
+
# Instance id constraint handler
+
# Record type constraint handler
+
# Property value constraint handler
+
 
+
OR
+
 
+
# Item/Relationship template handler
+
# XPath constraint handler
+
 
+
It is the responsibility of the handler factory class to create instances of each handler above.  The MDR toolkit automatically generates a handler factory.  See src/org.eclipse.cosmos.example.mdr.handlers.QueryHandlerFactory.java for the class generated.
+
 
+
== Implementing Query Handlers ==
+
 
+
This sample will provide four handlers in total:
+
 
+
# An item template handler
+
# An instance id constraint handler
+
# A record type constraint handler
+
# A relationship handler
+
 
+
<b>Create</b> the following classes for each handler under src/org.eclipse.cosmos.example.mdr.handlers:
+
 
+
# ItemTemplateHandler
+
# ItemInstanceIdHandler
+
# ItemRecordTypeHandler
+
# RelationshipTemplateHandler
+
 
+
In addition to the four classes above, create an interface called "ICMDBfSampleConstants" under the same package to contain constants commonly used between handlers.  The content of the interface, <b>ICMDBfSampleConstants</b>, appears below:
+
<pre>
+
package org.eclipse.cosmos.example.mdr.handlers;
+
 
+
/**
+
* Constants used by this CMDBf query sample
+
*/
+
public interface ICMDBfSampleConstants
+
{
+
/**
+
* The key for the data provider that will be
+
* stored in the initialization data of the constraint
+
* handlers
+
*/
+
public static final String DATA_PROVIDER = "org.eclipse.cosmos.samples.cmdbf.services.query.ICMDBfSampleConstants";
+
}
+
</pre>
+
 
+
<b>ItemTemplateHandler</b> is there to simply process item templates that do not contain any constraints.  The content of the class appears below:
+
 
+
<pre>
+
package org.eclipse.cosmos.example.mdr.handlers;
+
 
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.common.CMDBfServiceException;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.service.impl.AbstractItemTemplateHandler;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.transform.response.artifacts.IItemConvertible;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.transform.response.artifacts.INodes;
+
 
+
/**
+
* An item template handler is invoked prior to invoking any constraint handler
+
* for item templates.
+
*/
+
public class ItemTemplateHandler extends AbstractItemTemplateHandler
+
{
+
 
+
/**
+
* This method is only invoked if there are no constraints included in an
+
* item template.
+
*
+
* @param nodes The nodes element to append items to
+
*/
+
protected void appendAllItems(INodes nodes) throws CMDBfServiceException
+
{
+
XMLRepository repo = (XMLRepository)getValue(ICMDBfSampleConstants.DATA_PROVIDER);
+
addItems(nodes, repo.classes);
+
addItems(nodes, repo.students);
+
addItems(nodes, repo.teachers);
+
}
+
 
+
+
/**
+
* A convenient method used to add individual nodes to the
+
* INodes instance passed in.
+
*
+
* @param nodes Container for individual nodes
+
* @param itemConvertibles Elements that are convertible to an Item
+
*/
+
private void addItems(INodes nodes, IItemConvertible[] itemConvertibles)
+
{
+
for (int i = 0; i < itemConvertibles.length; i++)
+
{
+
nodes.addItem(itemConvertibles[i].toItem(nodes));
+
}
+
}
+
}
+
</pre> 
+
 
+
The instance id constraint is used to locate items based on the id attribute of the student/teacher element or the course code defined for a class element. The implementation simply walks through students, teachers, and classes to locate items that match the instance id constraint.  The content of <b>ItemInstanceIdHandler</b> appears below:
+
 
+
<pre>
+
package org.eclipse.cosmos.example.mdr.handlers;
+
 
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.common.CMDBfServiceException;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.service.impl.AbstractItemConstraintHandler;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.transform.input.artifacts.IConstraint;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.transform.input.artifacts.IInstanceIdConstraint;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.transform.response.artifacts.INodes;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.transform.response.artifacts.QueryOutputArtifactFactory;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.transform.artifacts.IInstanceId;
+
import org.eclipse.cosmos.example.mdr.handlers.XMLRepository.SchoolMember;
+
 
+
/**
+
* This is the handler class for instance id constraints included
+
* in item templates.  Adopters can either provide a direct implementation of
+
* IItemConstraintHandler or extend AbstractItemConstraintHandler
+
*/
+
public class ItemInstanceIdHandler extends AbstractItemConstraintHandler
+
{
+
@Override
+
protected INodes handle(INodes context, IConstraint constraint) throws CMDBfServiceException
+
{
+
INodes result = QueryOutputArtifactFactory.getInstance().createNodes(context.getId());
+
IInstanceIdConstraint instanceIdConstraint = (IInstanceIdConstraint)constraint;
+
IInstanceId[] instanceIds = instanceIdConstraint.getInstanceIds();
+
for (int i = 0; i < instanceIds.length; i++) {
+
if (!XMLRepository.MDR_ID.equals(instanceIds[i].getMdrId()
+
.toString())) {
+
continue;
+
}
+
String localId = instanceIds[i].getLocalId().toString();
+
XMLRepository repo = (XMLRepository) getValue(ICMDBfSampleConstants.DATA_PROVIDER);
+
// Traverse the students
+
traverseSchoolMembers(result, localId, repo.students);
+
// Traverse the teachers
+
traverseSchoolMembers(result, localId, repo.teachers);
+
// Traverse the classes
+
for (int j = 0; j < repo.classes.length; j++)
+
{
+
if (localId.equals(repo.classes[j].courseCode))
+
{
+
result.addItem(repo.classes[j]);
+
}
+
}
+
}
+
return result;
+
}
+
+
private void traverseSchoolMembers (INodes result, String localId, SchoolMember[] members)
+
{
+
for (int i = 0; i < members.length; i++)
+
{
+
if (localId.equals(members[i].identity.id))
+
{
+
result.addItem(members[i]);
+
}
+
}
+
}
+
}
+
</pre>
+
 
+
Similarly, ItemRecordTypeHandler is used to process record type constraints.  The handler supports three record types: student, teacher, and class.  The content of <b>ItemRecordTypeHandler</b> appears below:
+
 
+
<pre>
+
package org.eclipse.cosmos.example.mdr.handlers;
+
 
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.common.CMDBfServiceException;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.service.IItemConstraintHandler;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.service.impl.AbstractItemConstraintHandler;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.transform.input.artifacts.IConstraint;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.transform.input.artifacts.IRecordType;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.transform.response.artifacts.INodes;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.transform.response.artifacts.QueryOutputArtifactFactory;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.transform.artifacts.IGraphElement;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.transform.artifacts.IItem;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.transform.artifacts.IRecord;
+
import org.eclipse.cosmos.example.mdr.handlers.XMLRepository.ClassSession;
+
import org.eclipse.cosmos.example.mdr.handlers.XMLRepository.SchoolMember;
+
import org.eclipse.cosmos.example.mdr.handlers.XMLRepository.Student;
+
import org.eclipse.cosmos.example.mdr.handlers.XMLRepository.Teacher;
+
 
+
/**
+
* This is the handler for the record type constraint specified in
+
* and item template.  Adopters can either extend AbstractItemConstraintHandler
+
* or provide a direct implementation of {@link IItemConstraintHandler}
+
*/
+
public class ItemRecordTypeHandler extends AbstractItemConstraintHandler
+
{
+
/**
+
* Record type representing student
+
*/
+
private static final String RECORD_TYPE_STUDENT = "student";
+
+
/**
+
* Record type representing teacher
+
*/
+
private static final String RECORD_TYPE_TEACHER = "teacher";
+
+
/**
+
* Record type representing class
+
*/
+
private static final String RECORD_TYPE_CLASS = "class";
+
+
 
+
@Override
+
protected INodes handle(INodes context, IConstraint constraint) throws CMDBfServiceException
+
{
+
IRecordType recordType = (IRecordType)constraint;
+
String localName = recordType.getLocalName();
+
XMLRepository repo = (XMLRepository)getValue(ICMDBfSampleConstants.DATA_PROVIDER);
+
INodes result = QueryOutputArtifactFactory.getInstance().createNodes(context.getId());
+
+
// If the record type constraint includes all items as its context
+
if (context.isStartingContext())
+
{
+
if (RECORD_TYPE_STUDENT.equals(localName))
+
{
+
addSchoolMembers(result, repo.students);
+
}
+
else if (RECORD_TYPE_TEACHER.equals(localName))
+
{
+
addSchoolMembers(result, repo.teachers);
+
}
+
else if (RECORD_TYPE_CLASS.equals(localName))
+
{
+
for (int i = 0; i < repo.classes.length; i++)
+
{
+
result.addItem(repo.classes[i]);
+
}
+
}
+
+
return result;
+
}
+
+
IGraphElement[] elements = context.getElements();
+
for (int i = 0; i < elements.length; i++)
+
{
+
IRecord[] records = elements[i].getRecords();
+
for (int j = 0; j < records.length; j++)
+
{
+
if (RECORD_TYPE_STUDENT.equals(localName) && records[j].getValue() instanceof Student)
+
{
+
result.addItem((IItem)elements[i]);
+
continue;
+
}
+
else if (RECORD_TYPE_TEACHER.equals(localName) && records[j].getValue() instanceof Teacher)
+
{
+
result.addItem((IItem)elements[i]);
+
continue;
+
}
+
else if (RECORD_TYPE_CLASS.equals(localName) && records[j].getValue() instanceof ClassSession)
+
{
+
result.addItem((IItem)elements[i]);
+
continue;
+
}
+
}
+
}
+
+
return result;
+
}
+
 
+
private void addSchoolMembers(INodes result, SchoolMember[] members)
+
{
+
for (int i = 0; i < members.length; i++)
+
{
+
result.addItem(members[i]);
+
}
+
}
+
}
+
</pre>
+
 
+
Finally, RelationshipTemplateHandler is used to process one type of relationship: i.e. the relationship between a teacher and a student.  Given that there is only one relationship type defined, the input is processed in a relationship template handler.  Typically this would be defined in a record type constraint for relationship templates.  The class always assumes that the source is a teacher and the target is a student.  The relationship is always teacher X teaches student Y.  The code for <b>RelationshipTemplateHandler </b> appears below:
+
 
+
<pre>
+
package org.eclipse.cosmos.example.mdr.handlers;
+
 
+
import java.util.ArrayList;
+
import java.util.List;
+
 
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.common.CMDBfServiceException;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.service.IRelationshipTemplateHandler;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.service.impl.AbstractQueryHandler;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.transform.input.artifacts.IRelationshipTemplate;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.transform.response.artifacts.IEdges;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.transform.response.artifacts.IQueryResult;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.transform.response.artifacts.QueryOutputArtifactFactory;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.transform.artifacts.IItem;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.transform.artifacts.IRecord;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.transform.artifacts.IRelationship;
+
import org.eclipse.cosmos.example.mdr.handlers.XMLRepository.ClassSession;
+
import org.eclipse.cosmos.example.mdr.handlers.XMLRepository.Student;
+
import org.eclipse.cosmos.example.mdr.handlers.XMLRepository.Teacher;
+
 
+
/**
+
* Represents the relationship record type handler.  There is only one type
+
* of relationship that this handler accepts: "teaches".  The "teaches"
+
* relationship can only exist between a teacher A and a student B (i.e.
+
* A teaches B). 
+
* Adopters can either extend AbstractRelationshipConstraintHandler or provide
+
* a direct implementation of IRelationshipConstraintHandler
+
*/
+
public class RelationshipTemplateHandler extends AbstractQueryHandler implements IRelationshipTemplateHandler
+
{
+
public IEdges execute(IQueryResult context, IRelationshipTemplate relationshipTemplate, IItem source, IItem target) throws CMDBfServiceException
+
{
+
IEdges results = QueryOutputArtifactFactory.getInstance().createEdges(relationshipTemplate);
+
IRecord[] sourceRecords = source.getRecords();
+
IRecord[] targetRecords = target.getRecords();
+
+
// Only one record is expected
+
if (sourceRecords.length != 1 || targetRecords.length != 1)
+
{
+
return results;
+
}
+
+
if (sourceRecords[0].getValue() instanceof Teacher && targetRecords[0].getValue() instanceof Student)
+
{
+
XMLRepository repo = (XMLRepository)getValue(ICMDBfSampleConstants.DATA_PROVIDER);
+
String teacherId = ((Teacher)sourceRecords[0].getValue()).identity.id;
+
String studentId = ((Student)targetRecords[0].getValue()).identity.id;
+
+
ClassSession[] classSessions = findClass (repo, teacherId, studentId);
+
for (int i = 0; i < classSessions.length; i++)
+
{
+
IRelationship relationship = classSessions[i].toRelationship(results);
+
relationship.setSourceId(QueryOutputArtifactFactory.getInstance().createInstanceId(XMLRepository.MDR_ID, teacherId));
+
relationship.setTargetId(QueryOutputArtifactFactory.getInstance().createInstanceId(XMLRepository.MDR_ID, studentId));
+
results.addRelationship(relationship);
+
}
+
}
+
+
return results;
+
}
+
+
private ClassSession[] findClass(XMLRepository repo, String teacherId, String studentId)
+
{
+
List<ClassSession> discoveredClasses = new ArrayList<ClassSession>();
+
ClassSession[] classes = repo.classes;
+
for (int i = 0; i < classes.length; i++)
+
{
+
if (teacherId.equals(classes[i].teacher.identity.id))
+
{
+
Student[] students = classes[i].students;
+
for (int j = 0; j < students.length; j++)
+
{
+
if (studentId.equals(students[j].identity.id))
+
{
+
discoveredClasses.add(classes[i]);
+
}
+
}
+
}
+
}
+
+
return discoveredClasses.toArray(new ClassSession[discoveredClasses.size()]);
+
}
+
}
+
</pre>
+
 
+
This completes the implementation for all supported query handlers.  What remains to be done is the factory class to instantiate instances of each handler.  Open the generated class org.eclipse.cosmos.example.mdr.handlers.QueryHandlerFactory and add the following content:
+
 
+
<pre>
+
package org.eclipse.cosmos.example.mdr.handlers;
+
 
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.common.CMDBfServiceException;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.service.IItemConstraintHandler;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.service.IItemTemplateHandler;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.service.IRelationshipTemplateHandler;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.service.impl.AbstractQueryHandlerFactory;
+
 
+
/**
+
* This factory class is used to create handlers for the selectors
+
* that are applicable to the XML repository MDR.  Adopters can either
+
* extend AbstractSelectorHandlerFactory or provide a direct
+
* implementation of ISelectorHandlerFactory
+
*/
+
public class QueryHandlerFactory extends AbstractQueryHandlerFactory
+
{
+
private static QueryHandlerFactory instance;
+
+
/**
+
* Make the constructor invisible
+
*/
+
private QueryHandlerFactory()
+
{
+
}
+
+
public static QueryHandlerFactory getInstance()
+
{
+
if (instance == null)
+
{
+
instance = new QueryHandlerFactory();
+
}
+
return instance;
+
}
+
+
@Override
+
protected IItemConstraintHandler createItemInstanceHandler()
+
{
+
return new ItemInstanceIdHandler();
+
}
+
+
@Override
+
protected IItemConstraintHandler createItemRecordHandler()
+
{
+
return new ItemRecordTypeHandler();
+
}
+
+
@Override
+
protected IItemTemplateHandler createItemHandler() throws CMDBfServiceException
+
{
+
return new ItemTemplateHandler();
+
}
+
+
@Override
+
protected IRelationshipTemplateHandler createRelationshipHandler() throws CMDBfServiceException
+
{
+
return new RelationshipTemplateHandler();
+
}
+
}
+
</pre>
+
 
+
== Testing the Query Service ==
+
 
+
The easiest way of testing a query service for an MDR is through JUnit tests.  This section demonstrates how the query service can be tested independently from other COSMOS components.  The code included in this section can easily be incorporated in a JUnit to automatically test the results against an expected outcome.  Follow the instructions below to test the query service:
+
 
+
# Create a query request under <code>org.eclipse.cosmos.example.mdr/src</code> called <b>teaches-relationship.xml</b>
+
# Create a new class called <b>QueryLauncher</b> under the same package as the handlers (i.e. org.eclipse.cosmos.example.mdr.handlers).
+
 
+
Use the content below for the query request.  This file queries for all students that are taught by teacher staff01.
+
<pre>
+
 
+
<?xml version="1.0" encoding="UTF-8"?>
+
 
+
<!-- This query selects all students taught by the teacher with -->
+
<!-- the id: "staff01" -->
+
<s:query xmlns:s="http://cmdbf.org/schema/1-0-0/datamodel">
+
<s:itemTemplate id="teacher">
+
<s:instanceIdConstraint>
+
<s:instanceId>
+
<s:mdrId>org.eclipse.cosmos.samples.cmdbf.XMLRepository</s:mdrId>
+
<s:localId>staff01</s:localId>
+
</s:instanceId>
+
</s:instanceIdConstraint>
+
</s:itemTemplate>
+
+
<s:itemTemplate id="students">
+
<s:recordConstraint>
+
<s:recordType namespace="" localName="student"/>
+
</s:recordConstraint>
+
</s:itemTemplate>
+
+
<s:relationshipTemplate id="reference">
+
<s:sourceTemplate ref="teacher"/>
+
<s:targetTemplate ref="students"/>
+
</s:relationshipTemplate>
+
</s:query>
+
 
+
</pre>
+
 
+
Here's the content for <b>QueryLauncher</b>.  The main method simply uses the content of teaches-relationship.xml to submit a CMDBf query:
+
 
+
<pre>
+
package org.eclipse.cosmos.example.mdr.handlers;
+
 
+
 
+
import java.io.IOException;
+
import java.io.InputStream;
+
import java.net.URISyntaxException;
+
import java.util.Hashtable;
+
import java.util.Map;
+
 
+
import javax.xml.parsers.ParserConfigurationException;
+
 
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.common.CMDBfServiceException;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.service.impl.CMDBfQueryOperation;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.transform.QueryOutputTransformer;
+
import org.eclipse.cosmos.dc.provisional.cmdbf.services.query.transform.response.artifacts.IQueryResult;
+
import org.xml.sax.SAXException;
+
 
+
/**
+
* The main class used to run the CMDBf queries.  A set of query
+
* files exist under the source directory.  Adjust the queryFile field to
+
* run the correct CMDBf query.
+
*/
+
public class QueryLauncher
+
{
+
private static final String queryFile = "teaches-relationship.xml";
+
+
 
+
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException, IllegalArgumentException, URISyntaxException, CMDBfServiceException
+
{
+
// Run the query
+
InputStream query = QueryLauncher.class.getClassLoader().getResourceAsStream(queryFile);
+
CMDBfQueryOperation queryOperation = new CMDBfQueryOperation(QueryHandlerFactory.getInstance(), null);
+
Map<String, Object> init = new Hashtable<String, Object>();
+
init.put(ICMDBfSampleConstants.DATA_PROVIDER, new XMLRepository());
+
queryOperation.initialize(init);
+
IQueryResult result = queryOperation.execute(query);
+
+
// Transform and output the query
+
InputStream resultStream = QueryOutputTransformer.transform(result);
+
byte[] buffer = new byte[1024];
+
while (resultStream.available() > 0)
+
{
+
int chars = resultStream.read(buffer);
+
System.out.print(new String(buffer, 0, chars));
+
}
+
}
+
 
+
}
+
 
+
</pre>
+
 
+
Once executed, the output of the query should be printed out to the console.  The output will look something similar to:
+
 
+
<pre>
+
<cmdbf:queryResult xmlns:cmdbf="http://cmdbf.org/schema/1-0-0/datamodel">
+
<cmdbf:nodes templateId="teacher">
+
<cmdbf:item>
+
<cmdbf:record xmlns="http://school">
+
 
+
<teacher>
+
<identity firstName="Dawn" lastName="Johnson" id="staff01"/>
+
</teacher>
+
 
+
<cmdbf:recordMetadata>
+
<cmdbf:recordId>staff01</cmdbf:recordId>
+
</cmdbf:recordMetadata>
+
</cmdbf:record>
+
<cmdbf:instanceId>
+
<cmdbf:mdrId>org.eclipse.cosmos.samples.cmdbf.XMLRepository</cmdbf:mdrId>
+
<cmdbf:localId>staff01</cmdbf:localId>
+
</cmdbf:instanceId>
+
</cmdbf:item>
+
</cmdbf:nodes>
+
<cmdbf:nodes templateId="students">
+
<cmdbf:item>
+
<cmdbf:record xmlns="http://school">
+
 
+
<student>
+
<identity firstName="Mike" lastName="Lee" id="03"/>
+
</student>
+
 
+
<cmdbf:recordMetadata>
+
<cmdbf:recordId>03</cmdbf:recordId>
+
</cmdbf:recordMetadata>
+
</cmdbf:record>
+
<cmdbf:instanceId>
+
<cmdbf:mdrId>org.eclipse.cosmos.samples.cmdbf.XMLRepository</cmdbf:mdrId>
+
<cmdbf:localId>03</cmdbf:localId>
+
</cmdbf:instanceId>
+
</cmdbf:item>
+
<cmdbf:item>
+
<cmdbf:record xmlns="http://school">
+
 
+
<student>
+
<identity firstName="Bob" lastName="Davidson" id="01"/>
+
</student>
+
 
+
<cmdbf:recordMetadata>
+
<cmdbf:recordId>01</cmdbf:recordId>
+
</cmdbf:recordMetadata>
+
</cmdbf:record>
+
<cmdbf:instanceId>
+
<cmdbf:mdrId>org.eclipse.cosmos.samples.cmdbf.XMLRepository</cmdbf:mdrId>
+
<cmdbf:localId>01</cmdbf:localId>
+
</cmdbf:instanceId>
+
</cmdbf:item>
+
</cmdbf:nodes>
+
<cmdbf:edges templateId="reference">
+
<cmdbf:relationship>
+
<cmdbf:source>
+
<cmdbf:mdrId>org.eclipse.cosmos.samples.cmdbf.XMLRepository</cmdbf:mdrId>
+
<cmdbf:localId>staff01</cmdbf:localId>
+
</cmdbf:source>
+
<cmdbf:target>
+
<cmdbf:mdrId>org.eclipse.cosmos.samples.cmdbf.XMLRepository</cmdbf:mdrId>
+
<cmdbf:localId>03</cmdbf:localId>
+
</cmdbf:target>
+
<cmdbf:record xmlns="http://school">
+
 
+
<class name="Economics" courseCode="ECM01">
+
<students>
+
  <enrolledStudent idRef="01"/>
+
  <enrolledStudent idRef="03"/>
+
</students>
+
<teacher idRef="staff01"/>
+
</class>
+
 
+
<cmdbf:recordMetadata>
+
<cmdbf:recordId>ECM01</cmdbf:recordId>
+
</cmdbf:recordMetadata>
+
</cmdbf:record>
+
<cmdbf:instanceId>
+
<cmdbf:mdrId>org.eclipse.cosmos.samples.cmdbf.XMLRepository</cmdbf:mdrId>
+
<cmdbf:localId>ECM01</cmdbf:localId>
+
</cmdbf:instanceId>
+
</cmdbf:relationship>
+
<cmdbf:relationship>
+
<cmdbf:source>
+
<cmdbf:mdrId>org.eclipse.cosmos.samples.cmdbf.XMLRepository</cmdbf:mdrId>
+
<cmdbf:localId>staff01</cmdbf:localId>
+
</cmdbf:source>
+
<cmdbf:target>
+
<cmdbf:mdrId>org.eclipse.cosmos.samples.cmdbf.XMLRepository</cmdbf:mdrId>
+
<cmdbf:localId>01</cmdbf:localId>
+
</cmdbf:target>
+
<cmdbf:record xmlns="http://school">
+
 
+
<class name="Economics" courseCode="ECM01">
+
<students>
+
  <enrolledStudent idRef="01"/>
+
  <enrolledStudent idRef="03"/>
+
</students>
+
<teacher idRef="staff01"/>
+
</class>
+
 
+
<cmdbf:recordMetadata>
+
<cmdbf:recordId>ECM01</cmdbf:recordId>
+
</cmdbf:recordMetadata>
+
</cmdbf:record>
+
<cmdbf:instanceId>
+
<cmdbf:mdrId>org.eclipse.cosmos.samples.cmdbf.XMLRepository</cmdbf:mdrId>
+
<cmdbf:localId>ECM01</cmdbf:localId>
+
</cmdbf:instanceId>
+
</cmdbf:relationship>
+
</cmdbf:edges>
+
</cmdbf:queryResult>
+
 
+
</pre>
+
 
+
= Student-Teacher Client Proxy =
+
 
+
COSMOS provides a remote client proxy for invoking the CMDBf query service.  Since this example implements the query service, we can use the query service client to invoke the query operation. 
+
 
+
Here is a code snippet for invoking the query service using the query service client.  This example loads a query from a file, invokes the GraphQuery operation of the Example MDR query service, and prints out the query response in the console. 
+
 
+
<pre>
+
// EPR of the query service
+
String queryServieEpr = "http://localhost:8080/axis2/services/ExampleMdrQueryService";
+
 
+
// instantiate the query service client
+
QueryServiceClient client = new QueryServiceClient(queryServieEpr);
+
 
+
// path to a file that contains a CMDBf query
+
String filepath = "c:\cosmos-demo\cosmos-client\cmdbfQuery\ExampleMDR";
+
 
+
try {
+
    // loads the query into a DOM tree
+
    Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new File(queryFile));
+
    Element elem = doc.getDocumentElement();
+
 
+
    // invokes the query
+
    Element response = client.graphQuery(elem);
+
   
+
    // Writes the response using a StringWriter
+
    TransformerFactory tf = TransformerFactory.newInstance();
+
    Transformer trans = tf.newTransformer();
+
    StringWriter sw = new StringWriter();
+
    trans.transform(new DOMSource(response), new StreamResult(sw));
+
 
+
    // prints out the response
+
    System.out.println("Query response:");
+
    System.out.println(sw.toString());
+
   
+
} catch (CMDBfException cmdbfex) {
+
    // In case the query operation returns a SOAP fault,
+
    // here is how you can catch the fault and inspect the fault message
+
    if (cmdbfex.getCause() instanceof AxisFault) {
+
        AxisFault axisfault = (AxisFault) cmdbfex.getCause();
+
        System.out.println("Fault code: " + axisfault.getFaultCode());
+
        System.out.println("Fault subcode: " + axisfault.getFaultSubCodes());
+
        System.out.println("Fault message: " + axisfault.getMessage());
+
        System.out.println("Fault details: " + axisfault.getDetail());
+
    }
+
}
+
</pre>
+
 
+
= Adding Custom Capabilities =
+
 
+
Besides supporting the CMDBf query and registration services, a data manager can also provide other web services.  WTP provide tooling for creating web services.  Refer to the Reference section for links to tutorials on how to create web services.  After you have created the web service, update the services.xml file to include the definition of the new web service. 
+
 
+
 
+
 
+
= Running Student-Teacher MDR in Eclipse =
+
 
+
The example MDR can be tested by running within eclipse.  Following steps to run the Example MDR. 
+
 
+
# Right click on the web project, and select Run As... > Run on Server
+
# Select Tomcat 5.5 server, and click Next
+
# Click the Finish button in the next screen.
+
 
+
You may want to run the web service in debug mode so that you can step through the code.  To run in debug mode, select "Debug as..." instead of "Run As..." in step 1 above.
+
 
+
= Deploying Student-Teacher MDR in Tomcat =
+
 
+
After you have tested am MDR in eclipse, you can deploy it on a Tomcat server for the production environment.  You first need to have Axis2 web archive (version 1.3) installed in tomcat, which can be downloaded from here: http://ws.apache.org/axis2/download/1_3/download.cgi.  Then you need to package the web service in axis archive (AAR) format, which has the following directory structure:
+
 
+
<data manager name>/lib/
+
                    /META-INF/
+
                    /<class files>
+
 
+
The root directory is the name of the data manager.  It will be used as the axis2 service group name.  The lib directory contains all dependency jar files.  META-INF directory contains all WSDL and XSD files for the web service definition, as well as the services.xml file.  The class files are also packaged in their corresponding Java package directory structure.  The Student-Teacher MDR will have the following structure:
+
 
+
<pre>
+
ExampleMdr/lib/*.jar
+
          /META-INF/cmdbfQuery.wsdl
+
                  /QueryService.wsdl
+
                  /services.xml
+
                  /cmdbfDatamodel.xsd
+
          /org/eclipse/cosmos/provisional/example/mdr/ExampleMdr.class
+
</pre>
+
 
+
This web service directory can then be copied to the axis2 services directory (<tomcat>/webappsaxis2/WEB-INF/services).
+
 
+
= Reference =
+
* Tutorials for using WTP to create web services
+
** http://www.eclipse.org/webtools/community/tutorials/BottomUpAxis2WebService/bu_tutorial.html
+
** http://www.eclipse.org/webtools/community/tutorials/TopDownAxis2WebService/td_tutorial.html
+
 
+
  
 
[[Category:COSMOS_Development_Guide]]
 
[[Category:COSMOS_Development_Guide]]

Latest revision as of 16:26, 14 November 2008

COSMOS Wiki > COSMOS Document Plan > COSMOS Manual Guide

The most current content for this documentation is found here: http://www.eclipse.org/cosmos/documents/v1.0/devguide/cosmosdevguide04.htm#HDRDQX1CREATINGADATAMANAGER

Back to the top