BACK
MobyCore API
MobyCore is an API to execute BioMoby services. It supports both synchronous and asynchronous services. Library relies on JAX-WS 2.1 API that is a part of
Java 6. It also works on JEE5 where JAX-WS is a part of the platform. In case of using Java 5, JAX-WS must be present in a classpath.
Some essencial classes and packages of the library are:
org.inb.biomoby.shared.datatypes.*
|
This package contains BioMoby primitive classes (such as MobyString, MobyInteger...)
|
org.inb.biomoby.shared.message.*
|
Package contains classes related to BioMoby message structure (MobyMessage, MobyData, MobySimple...)
|
org.inb.biomoby.shared.registry.*
|
Classes in this package represent artifacts from BioMoby Registry (such as description of services or datatypes)
|
MobyMessageContext.class
|
This is a JAXB Context cache. JAXB Context has all BioMoby artefacts to convert them into an XML.
|
MobyDispatch.class
|
The class executes a BioMoby service.
|
Generating JAXB-annotated ontology classes
Even MobyCore may work without generated ontology classes, they facilitate a development.
Generated by MobyGenerator classes are nothing more than JAXB annotated beans with properties.
Here is an example of generated datatype class:
@XmlRootElement(name="WeightedAminoAcidSequences")
@XmlType(name="WeightedAminoAcidSequences")
public class WeightedAminoAcidSequences extends AminoAcidSequence implements Serializable {
public List<? extends AminoAcidSequence> getAminoAcidSequence() {
return getAttributes("AminoAcidSequence");
}
public void addAminoAcidSequence(AminoAcidSequence aminoAcidSequence) {
putAttribute("AminoAcidSequence", aminoAcidSequence);
}
public WeightedObject getWeightedObject() {
return getAttribute("WeightedObject");
}
public void setWeightedObject(WeightedObject weightedObject) {
putAttribute("WeightedObject", weightedObject);
}
}
Executing synchronous BioMoby services
To execute a BioMoby service, first we have to prepare a message.
This is done by creating a MobyMessage object:
MobyObject object = new MobyObject("P00807", "UniProt");
MobySimple simple = new MobySimple(object, "id");
MobyData data = new MobyData(simple, "sip_1");
MobyMessage request = new MobyMessage(data);
Next step is to create a BioMoby service description. To execute a service we do not need a complete description.
Service service = new Service("getAminoAcidSequence", "inb.bsc.es");
service.setCategory(CATEGORY.moby);
service.setUrl("http://inb.bsc.es/cgi-bin/mobyServices/dispatchersRetrieval/Dispatcher.cgi");
Now we can create a MobyDispatch object and execute a service.
MobyDispatch dispatch = new MobyDispatch(service);
MobyMessage response = dispatch.invoke(request);
The result of the execution is another MobyMessage that contains a response (or possibly MobyExceptions).
MobyCore supposed to work with generated JAXB-annotated ontology classes. In case when a class can not be found, it is substituted
by a special object AnyMobyObject. This object facilitates property access through getAttribute() and
getAttributes() methods. Consider that we execute a service that return an AminoAcidSequence object and we do
not have AminoAcidSequence class generated. In this case we would have a AnyMobyObject instead of unknown to us AminoAcidSequence.
MobyString string = (MobyString) any.getAttribute("SequenceString");
Well, may be this is not the best example, because we still must know that service returns an AminoAcidSequence or its derivative.
MobySimple may contain either a primitive type or a complex one, so we have to check. Here is a simple method that traverse a given element:
public void traverse(AbstractMobyObject object) throws JAXBException
{
System.out.println(MobyMessageContext.getMobyName(object) + " " + object.getArticleName());
if (object instanceof MobyObject)
{
MobyObject complex = (MobyObject)object;
List<AbstractMobyObject> attributes = complex.getAttributes();
for (AbstractMobyObject o : attributes)
{
traverse(o);
}
}
}
Here we used a MobyMessageContext to resolve a BioMoby name for a given object.
AnyMobyObject can also be used to setup a datatype dynamically.
AnyMobyObject any = new AnyMobyObject("AminoAcidSequece");
any.putAttribute("SequenceString", new MobyString("ATCG"));
any.putAttribute("Length", new MobyInteger(4));
Even we can perfectly mix AnyMobyObject with ontology generated classes, it is better to use one way or another.
Here is an example of parsing a MobyMessage response:
MobyMessage response = dispatch.invoke(request);
if (response.hasExceptions())
{
throw response.getExceptions(); // MobyExceptions is a java Exception object!
}
ArrayList<MobyData> data_list = response.getMobyDataList();
if (data_list.isEmpty())
{
throw new Exception("Empty response!");
}
for (MobyData data : data_list)
{
List<MobyDataElement> elements = data.getMobyDataElements(); // for example a list of simples
for (MobyDataElement element : elements)
{
if (element instanceof MobySimple)
{
MobySimple simple = (MobySimple)element;
AbstractMobyObject object = simple.getObject();
if (object instanceof AminoAcidSequence)
{
AminoAcidSequence sequence = (AminoAcidSequence)object;
MobyString str = sequence.getSequenceString();
System.out.println(str.getString());
}
else if (object instanceof AnyMobyObject)
{
AnyMobyObject any = (AnyMobyObject)object;
AbstractMobyObject attr = any.getAttribute("SequenceString");
if (attr != null && attr instanceof MobyString)
{
MobyString str = (MobyString)attr;
System.out.println(str.getString());
}
else
{
throw new Exception(); // object has no "SequenceString" property of type MobyString
}
}
else
{
throw new Exception(); // expected AminoAcidSequence
}
}
else
{
throw new Exception(); // expected MobySimple
}
}
}
Executing asynchronous BioMoby services
BioMoby uses a subset of WSRF specification for the asynchrony.
The main difference between asynchronous and synchronous services is in a way of obtaining a result.
Note also that we set a service category to "moby-async".
The rest of the things are pretty the same as for synchronous invocation:
// AminoAcidSequence sequence = new AminoAcidSequence();
// sequence.setSequenceString(new MobyString("ATCG")):
// sequence.setLength(new MobyInteger(4));
AnyMobyObject sequence = new AnyMobyObject("AminoAcidSequence");
sequence.putAttribute("SequenceString", new MobyString("ATCG"));
sequence.putAttribute("Length", new MobyInteger(4));
MobySimple simple = new MobySimple(sequence, "sequence");
MobyData data = new MobyData(simple, "sip_1");
MobyMessage request = new MobyMessage(data);
Service service = new Service("runNCBIBlastp", null);
service.setCategory(CATEGORY.moby_async);
service.setUrl("http://inb.bsc.es/cgi-bin/mobyServices/dispatchers/asyncDispatcher.cgi");
MobyDispatch dispatch = new MobyDispatch(service);
MobyWSRFResource wsrf = dispatch.invokeAsync(request);
The result object is an WSRF resource through which we can poll to check our execution status:
while(true)
{
AnalysisEvent lsae = wsrf.getResourcePropertyStatus("sip_1");
Event event = lsae.getEvent();
if (event instanceof StateChanged)
{
StateChanged stateChanged = (StateChanged)event;
StateChanged.STATE state = stateChanged.getNewState();
if (state == StateChanged.STATE.completed)
{ // the resource (result) is ready
MobyMessage response = wsrf.getResourcePropertyResult("sip_1");
wsrf.destroy(); // we can remove a resource if we do not need it anymore
}
else if (state == StateChanged.STATE.created ||
state == StateChanged.STATE.running)
{ // the result is not ready
Thread.currentThread().sleep(2000);
continue;
}
}
// actually must be an error...
break;
}
An obtained MobyMessage parsed the same way as for synchronous service.