wiki:RuConnecting

Connecting a Resource User

This topic will describe a short client for the Rest Interfaces available in Sensei. All Sensei components have TestPut/Get example files that you can use as a starting base. The Restlet client library we use is that from Noelios Technologies and it's version 2. (http://www.restlet.org/about/).

If you have access to the Source Code Repository, all XML commincation is standardized by using XML Schemas in the XML/component directory, please also check the README file there. This section will also show different ways on how to parse the response.

Table of Contents

  1. Connecting a Resource User
  2. Small Example Java client
  3. Dealing with XML
    1. Using JAXB
    2. Using DOM Parsing
  4. REST URL Redirection (Peered RDs and AAA)

Small Example Java client

Writing Rest clients in any language is pretty easy, especially in Java. A short example is show below. Basically, you must create a class that extends the Client, create a Reference from the service URL and get the Response from the service.

        Reference itemsUri = new Reference(url + "/rpi");
        Response response = this.handle(new Request(Method.POST, itemsUri, sr));

When posting data and processing responses, it will be necessary to parse XML.

/**
 * <p>Resource Directory Helper class.</p>
 */
public class RDClient extends Client {

    /**
     * <p>Default constructor</p>
     * 
     * @param protocol  Protocol to use
     */
    public RDClient(Protocol protocol, String url) {
        super(protocol);
        this.url = url;
    }

....

    /**
     * <p>Add a resource description</p>
     * 
     * @param xmlRepresentation Resource Description to add in String format
     * @throws DAOException
     */
    public String addResourceDescription(String xmlRepresentation)
            throws DAOException {
        if (xmlRepresentation == null) {
            throw new DAOException("I will not add an empty resource description.");
        }

        String retVal = null;

        Reference itemsUri = new Reference(url + "/rpi");
        StringRepresentation sr = new StringRepresentation(xmlRepresentation,
                MediaType.TEXT_XML);

        logger.log(Level.FINER, "Commiting data to {0}. ", url);

        Response response = this.handle(new Request(Method.POST, itemsUri, sr));
        if (response != null) {
            if (response.getStatus().isSuccess()) {
                String stringResponse = response.getEntityAsText();
                Pattern pattern = Pattern.compile("<PublishedIDs>(.*)</PublishedIDs>");
                Matcher matcher = pattern.matcher(stringResponse);

`                // Check all occurance
                while (matcher.find()) {
                    String storageId = matcher.group();
                    if (storageId != null) {
                        try {
                            Integer i = new Integer(storageId);
                            retVal = storageId;
                            logger.log(Level.FINE, "Got storage-Id {0}", i);
                        } catch (NumberFormatException e) {
                            logger.log(Level.WARNING, "NumberFormatException when"
                                    + "getting storageId from response.\n{0}", e.getMessage());
                        }
                    }
                }

            }

            logger.log(Level.FINER, "RD responded with : {0}.",
                    response.getEntityAsText());
        }

        return retVal;
    }

Dealing with XML

There are many technologies that cand deal with XML. The most used are DOM and SaX. We will describe two ways to encode/decode XML. First is JAXB, that uses Java annotations and let java deal with the problem. The second method is the standard method: just parse the XML and work through the XML nodes and select what you need.

Using JAXB

Most of the time you would like to deal with XML by not touching it directly. JAXB lets you marshall and unmarshall XML by using annotations. For example, if you to get your Object into an XML form you marhall it like this.

        JAXB.marshal(e, buf);

(full method follows)

    /**
     * <p>Add a resource description</p>
     * 
     * @param e Resource Description to add
     * @return  If the operation failed or not
     * @throws DAOException
     */
    public String addResourceDescription(
            ResourceDescription e) throws DAOException {
        if (e == null) {
            throw new DAOException("I will not add an empty resource description.");
        }

        StringWriter buf = new StringWriter();
        JAXB.marshal(e, buf);
        String xmlRepresentation = buf.toString();

        return addResourceDescription(xmlRepresentation);
    }

For this to work, you must adnotate your resource, in our case ResourceDescription? like this:

/**
 * <p>ResourceDescription implementation</p>
 */
@Entity
@Table(name = "resource_cache")
@XmlRootElement(name = "Resource-Description")
public class ResourceDescription implements Serializable {
...

    /**
     * @return the name
     */
    @XmlElement(name = "Name")
    public String getName() {
        return name;
    }

    /**
     * @return the resourceId
     */
    @XmlElement(name = "Resource-ID")
    public String getResourceId() {
        return resourceId;
    }
}

Using DOM Parsing

The normal fashion way in which you would deal with XML is just parse it. This would be the way to get the !REST Response as and XML Document.

    /**
     * <p>List Entries</p>
     * 
     * @param offset    Offset start
     * @param limit     Limit of Resource Entries to get
     * @return          ArrayList of ResourceDescriptions
     * @throws DAOException
     */
    public ArrayList<ResourceDescription> listEntries(int offset, int limit) {
...
        Document doc = null;
        Status status = response.getStatus();

        if (status.isSuccess() || (status.isRedirection())) {
            try {
                DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                DocumentBuilder builder = null;
                builder = factory.newDocumentBuilder();
                doc = builder.parse(new InputSource(
                        new StringReader(response.getEntityAsText())));
            } catch (ParserConfigurationException e1) {
                throw new DAOException(e1);
            } catch (SAXException e1) {
                throw new DAOException(e1);
            } catch (IOException e1) {
                throw new DAOException(e1);
            }
        } else if (status.isConnectorError()) {
            throw new DAOException("Connection timeout while getting data from "
                    + url);
        } else {
            throw new DAOException("Some kind or error while getting data: "
                    + status.toString());
        }

        if (doc != null) {
            result = RDUtils.getRDFromXMLNode(doc, true);
        } else {
            throw new DAOException("Could not get a reponse.");
        }

...
    }

And parse it by using DOM

        NodeList nodeList = doc.getChildNodes();
        if ((nodeList != null) && ((nodeList.getLength() == 1))) {
            NodeList resultList = nodeList.item(0).getChildNodes();

            for (int i = 0; i < resultList.getLength(); i++) {
                Node n = resultList.item(i);

                String type = n.getNodeName();
                if (type.equalsIgnoreCase(RESULT_PUBLISHED)) {
...

REST URL Redirection (Peered RDs and AAA)

The last topic in this section relies on how the Sensei Framework works in case a resource can not respond to your request, but knows other services that do. Both the RD request and RAI get rerouted to other URLs through HTTP redirection. In the Resource Directory case, you get a redirect when you have peered RDs and the resource is not in the queried RD (see below). Another case, is when you query a AAA. If you do not have an authenticated session, then you get redirected to the SSO infrastructure.

As a resource user you must check the response status of the REST Response.

                org.restlet.data.Reference itemRef = new org.restlet.data.Reference(myURL); 
                List<RDDataRow> result = null;
                Response response = get(itemRef);
                Document doc = null;
                if (response != null) {
                        if (response.getStatus().getCode() == 307) {
                                logger.info("It is a redirection to " + response.getLocationRef());
                                
                                itemRef = response.getLocationRef(); 
                                response = get(itemRef);
                        }
                        doc = getDocumentFromResponse(response); 
                }

If the response is code 307, then check the hostname that responded. From there, you know how to react. If it's an RD, then do the request again, in case of AAA, authenticate and extract the security token and reuse the resulted SSL connection session to request the data again, this time having the token.

Last modified 13 years ago Last modified on Mar 2, 2011, 7:54:27 AM