<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Recent changes to OfflineOutputs</title><link>https://sourceforge.net/p/arcomem/wiki/OfflineOutputs/</link><description>Recent changes to OfflineOutputs</description><atom:link href="https://sourceforge.net/p/arcomem/wiki/OfflineOutputs/feed" rel="self"/><language>en</language><lastBuildDate>Wed, 19 Feb 2014 00:34:14 -0000</lastBuildDate><atom:link href="https://sourceforge.net/p/arcomem/wiki/OfflineOutputs/feed" rel="self" type="application/rss+xml"/><item><title>OfflineOutputs modified by John Arcoman</title><link>https://sourceforge.net/p/arcomem/wiki/OfflineOutputs/</link><description>&lt;div class="markdown_content"&gt;&lt;h1 id="outputting-data-from-offline-modules"&gt;Outputting Data from Offline Modules&lt;/h1&gt;
&lt;p&gt;Every offline processing module has the option of how it outputs its data.&lt;br /&gt;
It can output to a Hadoop sequence file, write some data back to the HBase or&lt;br /&gt;
it can output semantic information to a triple-store.&lt;/p&gt;
&lt;p&gt;Note that offline modules that work on sequence files, local files or the&lt;br /&gt;
triple-store are just basic Hadoop MapReduce jobs so extend the &lt;code&gt;MapReduceSpecGeneric&lt;/code&gt;&lt;br /&gt;
class that is part of the Hadoop framework.&lt;/p&gt;
&lt;h2 id="writing-output-to-a-sequence-file"&gt;Writing Output to a Sequence File&lt;/h2&gt;
&lt;p&gt;If a module writes large amounts of data or writes binary data that would not sensibly&lt;br /&gt;
need to be kept in the HBase, the module can use the Hadoop file system to write data&lt;br /&gt;
to a sequence file. Sequence files are available over the cluster, so the data that&lt;br /&gt;
is written to them can be used other tasks which might occur on other nodes.&lt;/p&gt;
&lt;p&gt;To write the output of a module to a sequence file, the module should extend the&lt;br /&gt;
&lt;a class="" href="/apidocs/eu/arcomem/framework/offline/OfflineProcess"&gt;&lt;code&gt;OfflineProcess&lt;/code&gt;&lt;/a&gt;&lt;br /&gt;
class as normal. However, the final generic type (the &lt;code&gt;OUTPUT_FORMAT&lt;/code&gt;)&lt;br /&gt;
should be of the type:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;SequenceFileOutput&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;KEY_TYPE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;VALUE_TYPE&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A sequence file, just like an HBase, is a key-value store, so the types of the key and&lt;br /&gt;
value need to be supplied. In most cases the &lt;code&gt;KEY_TYPE&lt;/code&gt; will be the same key type as the&lt;br /&gt;
HBase (you will key on the URI of the web object), which is &lt;code&gt;Text&lt;/code&gt;. If you\'re writing&lt;br /&gt;
binary you can use &lt;code&gt;BytesWritable&lt;/code&gt; as the value type (just a byte array of data).&lt;/p&gt;
&lt;p&gt;If the type is map-heavy, then the reducer needs to be the default reducer (rather than&lt;br /&gt;
the the &lt;a class="" href="../apidocs/eu/arcomem/framework/offline/util/NullReducer"&gt;&lt;code&gt;NullReducer&lt;/code&gt;&lt;/a&gt;).&lt;br /&gt;
This is because the sequence file is defined as the output of the&lt;br /&gt;
whole job (map and reduce), so the reducer needs to output the sequence file (the default&lt;br /&gt;
one will do this for you if you define your module to output a sequence file).&lt;/p&gt;
&lt;p&gt;The following shows a skeleton for a class that will map over the elements of the HBase&lt;br /&gt;
and then output a sequence file (with no reducer):&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;SequenceFileWriterModule&lt;/span&gt;
    &lt;span class="kr"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;OfflineProcess&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
        &lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BytesWritable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BytesWritable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;SequenceFileOutputFormat&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BytesWritable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;Override&lt;/span&gt;
    &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;Class&lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;?&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;OfflineProcessMapper&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BytesWritable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;getMapperClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;throws&lt;/span&gt; &lt;span class="nx"&gt;ClassNotFoundException&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;MyMapperClass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;class&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;SuppressWarnings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;unchecked&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;Override&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Reducer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BytesWritable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BytesWritable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;getReducerClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;throws&lt;/span&gt; &lt;span class="nx"&gt;ClassNotFoundException&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// we don't actually use the reducer, so the default one is returned&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Reducer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BytesWritable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BytesWritable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;Reducer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;class&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;Override&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;void&lt;/span&gt; &lt;span class="nx"&gt;setupJob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Job&lt;/span&gt; &lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setupJob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setNumReduceTasks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that we return a default reducer for the reducer class (rather than a&lt;br /&gt;
&lt;a class="" href="../apidocs/eu/arcomem/framework/offline/util/NullReducer"&gt;&lt;code&gt;NullReducer&lt;/code&gt;&lt;/a&gt;)&lt;br /&gt;
&lt;span&gt;[The double cast there is a fix for a generic bug in certain versions of Java]&lt;/span&gt;.&lt;/p&gt;
&lt;h2 id="writing-output-back-the-to-hbase"&gt;Writing Output back the to HBase&lt;/h2&gt;
&lt;p&gt;There may be modules which wish to store information into the HBase for better controlling the&lt;br /&gt;
input to subsequent tasks.&lt;/p&gt;
&lt;p&gt;The interface to rows of the HBase is provided by an API called&lt;br /&gt;
&lt;a class="" href="../apidocs/eu/arcomem/framework/AMResourceVersion"&gt;&lt;code&gt;AMResourceVersion&lt;/code&gt;&lt;/a&gt;.&lt;br /&gt;
This class provides methods for getting and setting values of a specific row in the HBase. If you want to store&lt;br /&gt;
information to this row, you need to ensure that an appropriate cell is available into which to store it.&lt;br /&gt;
To do this, you simply need to provide a name for the cell. The cell must be put within the \'Content\'&lt;br /&gt;
column family.  The usual way is to extend the&lt;br /&gt;
&lt;a class="" href="../apidocs/eu/arcomem/framework/AMResourceVersion"&gt;&lt;code&gt;AMResourceVersion&lt;/code&gt;&lt;/a&gt;&lt;br /&gt;
with your own methods for writing your data.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="n"&gt;MyResourceVersion&lt;/span&gt; &lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;AMResourceVersion&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;getMyData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getQualifierValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;ResourceVersion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CONTENT_CF&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;// Column family must be this&lt;/span&gt;
            &lt;span class="s"&gt;&amp;quot;my.data.cell&amp;quot;&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;setGateSimpleXml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;myData&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setQualifierValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;ResourceVersion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CONTENT_CF&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;// Column family must be this&lt;/span&gt;
            &lt;span class="s"&gt;&amp;quot;my.data.cell&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;myData&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Then, during the mapping or reducing, you can simply retrieve a row into your class&lt;br /&gt;
from the context then use your class to set and/or get values.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;MyResourceVersion&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getResource&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;getLatestRowVersion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;MyResourceVersion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;setMyData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;myData&amp;quot;&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;myData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getMyData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note: If the data is to be consistently used by many modules, it may be an idea to update the&lt;br /&gt;
&lt;a class="" href="../apidocs/eu/arcomem/framework/AMResourceVersion"&gt;&lt;code&gt;AMResourceVersion&lt;/code&gt;&lt;/a&gt;&lt;br /&gt;
class rather than extending it as has been done for &lt;code&gt;GateXml&lt;/code&gt; data.&lt;/p&gt;
&lt;h2 id="writing-to-the-triple-store"&gt;Writing to the Triple Store&lt;/h2&gt;
&lt;p&gt;The ARCOMEM framework provides a simple method for constructing a&lt;br /&gt;
&lt;a class="" href="../apidocs/eu/arcomem/framework/rdf/TripleStoreConnector"&gt;&lt;code&gt;TripleStoreConnector&lt;/code&gt;&lt;/a&gt;&lt;br /&gt;
object which will give access to a knowledgebase which can be queried or written to.&lt;br /&gt;
If your offline process requires this form of output, then in the&lt;br /&gt;
&lt;code&gt;setup(Job)&lt;/code&gt; method, the offline process can call&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;TripleStoreConnector&lt;/span&gt; &lt;span class="n"&gt;tsc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TripleStoreConnector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;newConnector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getConfig&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The&lt;br /&gt;
&lt;a href="../apidocs/eu/arcomem/framework/rdf/TripleStoreConnector.html#newConnector%28org.apache.hadoop.conf.Configuration%29"&gt;newConnector(config)&lt;/a&gt;&lt;br /&gt;
method takes a configuration object from which&lt;br /&gt;
it can determine which triple store connector implementation to invoke.&lt;br /&gt;
When running as a Hadoop Map-Reduce job, the configuration can be retrieved&lt;br /&gt;
from the task’s context as above.&lt;br /&gt;
This &lt;a class="" href="../apidocs/eu/arcomem/framework/rdf/TripleStoreConnector"&gt;&lt;code&gt;TripleStoreConnector&lt;/code&gt;&lt;/a&gt;&lt;br /&gt;
object has a&lt;br /&gt;
&lt;a href="../apidocs/eu/arcomem/framework/rdf/TripleStoreConnector.html#writeRDFDocument(java.io.InputStream,%20java.lang.String,%20org.openrdf.rio.RDFFormat)"&gt;&lt;tt&gt;writeRDF(String)&lt;/tt&gt;&lt;/a&gt;&lt;br /&gt;
and&lt;br /&gt;
&lt;a href="../apidocs/eu/arcomem/framework/rdf/TripleStoreConnector.html#writeTriple(org.openrdf.model.Statement)"&gt;&lt;tt&gt;writeTriple(Statement)&lt;/tt&gt;&lt;/a&gt;&lt;br /&gt;
methods which provide two separate means for writing data to the triple store.&lt;br /&gt;
The first allows the writing of a batch of data encoded in RDF while the second&lt;br /&gt;
allows single triples to be asserted into the knowledgebase. These methods&lt;br /&gt;
provide no form of validation to the data that any code passes to it&lt;br /&gt;
(unless the underlying triple store does this). So one way of providing a set&lt;br /&gt;
of triples that conform to the ARCOMEM ontology is to use the data-model&lt;br /&gt;
Java classes which are available in a separate subproject within the ARCOMEM&lt;br /&gt;
codebase (see the &lt;a class="" href="/p/arcomem/wiki/DataModel/"&gt;Data Model section&lt;/a&gt; for information).&lt;/p&gt;&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">John Arcoman</dc:creator><pubDate>Wed, 19 Feb 2014 00:34:14 -0000</pubDate><guid>https://sourceforge.netbf4763a3d076776667c7489697bec8dbbcbc3c1f</guid></item></channel></rss>