<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>JNBridge Blog</title>
	<atom:link href="http://www.jnbridge.com/jn/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jnbridge.com/jn</link>
	<description>Java and .NET Interoperability</description>
	<lastBuildDate>Tue, 07 May 2013 06:43:52 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Building an Excel add-in for HBase MapReduce</title>
		<link>http://www.jnbridge.com/jn/blog/2013/05/06/building-an-excel-add-in-for-hbase-mapreduce/</link>
		<comments>http://www.jnbridge.com/jn/blog/2013/05/06/building-an-excel-add-in-for-hbase-mapreduce/#comments</comments>
		<pubDate>Tue, 07 May 2013 06:40:59 +0000</pubDate>
		<dc:creator>William Heinzman</dc:creator>
				<category><![CDATA[JNBridgePro]]></category>
		<category><![CDATA[Labs]]></category>
		<category><![CDATA[Excel]]></category>
		<category><![CDATA[Hadoop]]></category>
		<category><![CDATA[HBase]]></category>

		<guid isPermaLink="false">http://www.jnbridge.com/jn/?p=1648</guid>
		<description><![CDATA[Summary This latest project from JNBridge Labs investigates building an Excel add-in for Hadoop HBase. As a Java framework, HBase applications must use Java APIs, resulting in single-platform solutions. A cross-platform HBase integrated solution, particularly one that provides business intelligence on the desktop, like Microsoft Excel, is unable to leverage the HBase remote client API. [...]]]></description>
				<content:encoded><![CDATA[<h3>Summary</h3>
<p><em>This latest project from JNBridge Labs investigates building an Excel add-in for Hadoop HBase. As a Java framework, HBase applications must use Java APIs, resulting in single-platform solutions. A cross-platform HBase integrated solution, particularly one that provides business intelligence on the desktop, like Microsoft Excel, is unable to leverage the HBase remote client API. This means using a lower level interoperability mechanism, like implementing a .NET Thrift client. The current project uses JNBridgePro for .NET-to-Java interoperability. It also leverages concepts and code from the previous lab, <a title="lastProjectLink" href="http://www.jnbridge.com/jn/blog/2012/10/10/building-a-linq-provider-for-hbase-mapreduce/">Building a LINQ provider for HBase MapReduce</a>, which investigated a LINQ extension for HBase.  </em></p>
<h3>Introduction</h3>
<p>Hadoop allows businesses to quickly analyze very large data sets. Hadoop can reduce ludicrous amounts of data to a meaningful answer in a short amount of time, however, without understanding the <em>shape</em> of your data, you run the risk of garbage in, garbage out. Analysis itself is an iterative process relying on investigation. Tools that aid data investigation provide a means to quickly view, sort, filter/reduce and represent data, making it possible to quickly find and understand patterns, trends and relationships.</p>
<p>Microsoft Excel has always been the ubiquitous off-the-shelf  tool for data analysis and it makes a ready-to-go front end for Hadoop. Excel can be extended using add-ins developed in Visual Studio using VSTO, <em>Visual Studio Tools for Office</em>. This lab will explore a simple Excel front-end to HBase MapReduce. The front-end will allow a user to view HBase tables and execute MapReduce jobs. The goal is to make the add-in generic with respect to the column definitions and data in a HBase table.</p>
<h3>Getting Started</h3>
<p>The components required for this lab are identical to those required in the previous lab, <a title="lastProjectLink" href="http://www.jnbridge.com/jn/blog/2012/10/10/building-a-linq-provider-for-hbase-mapreduce/">Building a LINQ provider for HBase MapReduce</a><em>. </em>Here&#8217;s a quick list of the components.</p>
<ol>
<li>Apache Hadoop Stack (see the previous lab&#8217;s <em>Getting Started</em> section for more information)</li>
<li>Visual Studio 2012</li>
<li>Eclipse</li>
<li>JNBridgePro 7.0</li>
<li>Office Developer Tools for Visual Studio 2012 (this includes VSTO).</li>
<li>Microsoft Office 2010</li>
</ol>
<h3>Calling Java from .NET: Creating proxies using JNBridgePro</h3>
<p>Since the Excel add-in is written in C#/.NET and needs to call several Java class APIs, the first step is to use the JNBridgePro plug-in for Visual Studio to create an assembly of proxies that represent the Java API. When a proxy of a Java class is instantiated in .NET, the real Java object is instantiated in the Java Virtual Machine. The JNBridgePro run-time manages communications, i.e. invoking methods, and syncing garbage collection between the .NET CLR and the JVM.</p>
<p>For this development step, as well as during run-time, a bunch of Hadoop, HBase and ZooKeeper JAR files must be available on the Windows machine. These can be scraped from a machine running the Hadoop stack (look in <em>/usr/lib/hadoop/lib</em>, <em>/usr/lib/hbase/lib</em>, etc.)</p>
<p>This is a screen shot of the <em>Edit Class Path</em> dialog for the JNBridgePro Visual Studio plug-in.</p>
<p style="padding-left: 30px"><a href="http://www.jnbridge.com/jn/blog/2012/10/10/building-a-linq-provider-for-hbase-mapreduce/editclasspath/" rel="attachment wp-att-1301"><img class="alignnone size-full wp-image-1301" style="margin-top: 4px;margin-bottom: 20px" src="http://www.jnbridge.com/jn/wp-content/blogs.dir/1/files/2012/10/EditClassPath.jpg" alt="" width="456" height="347" /></a></p>
<p>These are the JAR files required to create the .NET proxies. During run-time, three additional JAR files must be included in the JVM’s class path when initiating the bridge between the JVM and the CLR: <em>avro-1.5.4.jar</em>, <em>commons-httpclient-3.1.jar</em> and <em>slf4j-nop-1.6.1.jar</em> (the last JAR file inhibits logging by Hadoop and HBase).</p>
<p>Below, is a screen shot of the JNBridgePro proxy tool in Visual Studio. The left hand pane shows all the namespaces found in the JAR files shown in the above dialog. The required namespaces are <em>org.apache.hadoop.hbase.client</em> and <em>org.apache.hadoop.hbase.filter</em>. In addition, individual classes like <em>org.apache.hadoop.hbase.HBaseConfiguration</em> are required (see the link at the end of this blog to download the source).</p>
<p style="padding-left: 30px"> <a href="http://www.jnbridge.com/jn/blog/2012/10/10/building-a-linq-provider-for-hbase-mapreduce/proxytool/" rel="attachment wp-att-1306"><img class="alignnone  wp-image-1306" style="border: 1px solid black;margin-top: 4px;margin-bottom: 20px" src="http://www.jnbridge.com/jn/wp-content/blogs.dir/1/files/2012/10/proxytool.jpg" alt="" width="542" height="239" /></a></p>
<p>By clicking on the <strong>Add+</strong> button, the chosen classes, as well as every dependent class, will be found and displayed in the center pane. The right-hand pane displays the public members and methods of the Java <em>HTable</em> class. The last step is to build the proxy assembly, <em>DotNetToJavaProxies.dll</em>.</p>
<h3>Creating and populating an HBase Table</h3>
<p>It would be nice to have an HBase table loaded with data and provide an opportunity to test calling various HBase Java APIs from .NET. The simple data will consist of an IP address, like “88.240.129.183″ and the requested web page, for example “/zebra.html”. This lab will use the same table, <em>access_logs</em>, created for the previous lab, <a title="lastProjectLink" href="http://www.jnbridge.com/jn/blog/2012/10/10/building-a-linq-provider-for-hbase-mapreduce/">Building a LINQ provider for HBase MapReduce</a>. Please see the previous lab&#8217;s section, <em>Creating and populating an HBase Table</em>, for the code used to build this table.</p>
<h3>Building an Excel add-in</h3>
<p>The Excel add-in will consist of a single control pane. As the user interacts with the pane, underlying code accesses the Excel data model consisting of workbooks, worksheets and charts. Here&#8217;s what the completed add-in looks like.</p>
<p style="padding-left: 30px"><a href="http://www.jnbridge.com/jn/blog/2013/05/06/building-an-excel-add-in-for-hbase-mapreduce/addin/" rel="attachment wp-att-1655"><img class="alignnone  wp-image-1655" style="border: 1px solid black;margin-top: 4px;margin-bottom: 20px" src="http://www.jnbridge.com/jn/wp-content/blogs.dir/1/files/2013/03/AddIn.jpg" alt="" width="550" height="458" /></a></p>
<p>The class <em>HBasePane</em> is a .NET User Control. It consists of two groups, <em>View Table</em> and <em>Map Reduce</em>. The above screen shot shows the user controls labeled <em>Zookeeper Host</em>, <em>Table Name</em> and <em>Number of Records,</em> which all have user entered values. By clicking on the button, <em>View Records</em>, the user has loaded in 20 rows from the HBase table, <em>access_logs</em>.</p>
<p>Here&#8217;s the handler code for the button click event.</p>
<pre style="font-family: Verdana;font-size: 11;color: black;background: white">        <span style="color: blue">private</span> <span style="color: blue">void</span> viewTableButtonClick(<span style="color: blue">object</span> sender, <span style="color: #2b91af">EventArgs</span> e)
        {
            Excel.Worksheet activeWorksheet 
                 = ((Excel.Worksheet)Globals.ExcelHBaseAddIn.Application.ActiveSheet);
            activeWorksheet.Name = <span style="color: #a31515">"Records"</span>;
            Excel.Range navigator = activeWorksheet.get_Range(<span style="color: #a31515">"A1"</span>);
            <span style="color: blue">int</span> numRows = <span style="color: #2b91af">Decimal</span>.ToInt32(<span style="color: blue">this</span>.numberOfRecords.Value);
            <span style="color: green">// most of the work done here</span>
            <span style="color: blue">this</span>.columns = ViewHBaseTable.populateWorkSheet(navigator
                , <span style="color: blue">this</span>.hostName.Text
                , <span style="color: blue">this</span>.tableName.Text
                , numRows);
            <span style="color: green">// autofit the range</span>
            <span style="color: blue">int</span> numCols = <span style="color: blue">this</span>.columns.Count&lt;<span style="color: blue">string</span>&gt;();
            Excel.Range c1 = activeWorksheet.Cells[1, 1];
            Excel.Range c2 = activeWorksheet.Cells[numRows, numCols];
            <span style="color: blue">this</span>.cols = activeWorksheet.get_Range(c1, c2); 
            <span style="color: blue">this</span>.cols.EntireColumn.AutoFit();
            <span style="color: green">// populate the user controls with the column names</span>
            <span style="color: blue">this</span>.filterComboBox.Items.AddRange(<span style="color: blue">this</span>.columns);
            <span style="color: blue">this</span>.frequencyComboBox.Items.AddRange(<span style="color: blue">this</span>.columns);
        }</pre>
<p>All the work is done in the method, <em>ViewHBaseTable.populateWorkSheet()</em>. The user controls are <em>hostName</em>, <em>tableName</em> and <em>numberOfRecords</em>. The hostName control contains the address of the machine that&#8217;s running Zookeeper, which is responsible for managing connections from the HBase client API. Below is code from <em>populateWorkSheet()</em>. Notice that the HBase table <em>column family</em> and <em>cell</em> names are obtained using the methods<em> getFamily()</em> and <em>getQualifier() </em>along with the cell values. The method returns an array of strings that represents the column and cell names in the table. These are used to populate the combo box controls <em>filterComboBox</em> and <em>frequencyComboBox</em> in the group <em>Map Reduce</em>.</p>
<pre style="font-family: Verdana;font-size: 11;color: black;background: white">            Configuration hbaseConfig = HBaseConfiguration.create();
            hbaseConfig.set(<span style="color: #a31515">"hbase.zookeeper.quorum"</span>, hostName);
            <span style="color: blue">try</span>
            {
                HTable tbl = <span style="color: blue">new</span> HTable(hbaseConfig, tableName);
                Scan scan = <span style="color: blue">new</span> Scan();
                ResultScanner scanner = tbl.getScanner(scan);
                Result r;
                <span style="color: blue">while</span> (((r = scanner.next()) != <span style="color: blue">null</span>) &amp;&amp; ndx++ &lt; numRecords)
                {
                    List aList = r.list();
                    ListIterator li = aList.listIterator();
                    <span style="color: blue">while</span> (li.hasNext())
                    {
                        kv = (KeyValue)li.next();
                        familyName = Bytes.toString(kv.getFamily());
                        cellName = Bytes.toString(kv.getQualifier());
                        value = Bytes.toString(kv.getValue());
                        <span style="color: green">// make a unique list of all the column names</span>
                        <span style="color: blue">if</span> (!names.Contains(familyName + <span style="color: #a31515">":"</span> + cellName))
                        {
                            names.Add(familyName + <span style="color: #a31515">":"</span> + cellName);
                        }
                        <span style="color: green">// add headers</span>
                        <span style="color: blue">if</span> (currentRow == 2)
                        {
                            currentCell = navigator.Cells[1, currentColumn];
                            currentCell.Value2 = cellName;
                        }
                        currentCell = navigator.Cells[currentRow, currentColumn++];
                        currentCell.Value2 = value;
                    }
                    currentRow++;
                    currentColumn = 1;
                }
                scanner.close();
                tbl.close();
            }
            <span style="color: blue">catch</span> (<span style="color: #2b91af">Exception</span> ex)
            {
                <span style="color: blue">throw</span> ex;
            }
            <span style="color: blue">return</span> names.ToArray&lt;<span style="color: blue">string</span>&gt;();
        }</pre>
<h4>Generic filtering and frequency user interface</h4>
<p>Below is a close-up screenshot of the HBase pane. The interface in the <em>View Table</em> group allows the user to point to a Hadoop implementation, choose a table and the number of records to load into the active worksheet. Once that is done, the user can then define a MapReduce job using the controls in the <em>Map Reduce</em> group.</p>
<p><a href="http://www.jnbridge.com/jn/blog/2013/05/06/building-an-excel-add-in-for-hbase-mapreduce/panecloseup2/" rel="attachment wp-att-1717"><img class="alignnone  wp-image-1717" style="border: 1px solid black;margin-top: 4px;margin-bottom: 20px;margin-left: 30px" src="http://www.jnbridge.com/jn/wp-content/blogs.dir/1/files/2013/03/PaneCloseUp2.jpg" alt="" width="233" height="390" /></a></p>
<p>The user interface allows filtering on any one column. The combo box control labeled <em>Choose filter column</em> contains all the column names in the form <em>family:cell</em>. The text box labeled <em>FilterValue</em> is the filter which elides all rows where the chosen column  doesn&#8217;t match the filter value. The combo box labeled <em>Column to Count</em> is used to choose the column whose values will be grouped and counted. The above values ask the question: &#8220;<em>What are the pages—specifically the frequencies of the pages— visited by the IP address 80.240.129.183</em>&#8220;.</p>
<p>When the button, <em>Map Reduce,</em> is clicked, this handler is invoked:</p>
<pre style="font-family: Verdana;font-size: 11;color: black;background: white">        <span style="color: blue">private</span> <span style="color: blue">void</span> onMapRedButtonClick(<span style="color: blue">object</span> sender, <span style="color: #2b91af">EventArgs</span> e)
        {
            <span style="color: blue">this</span>.filterColumn = <span style="color: blue">this</span>.filterComboBox.Text;
            <span style="color: blue">this</span>.filterValue = <span style="color: blue">this</span>.filterValueTextBox.Text;
            <span style="color: blue">this</span>.frequencyColumn = <span style="color: blue">this</span>.frequencyComboBox.Text;
            Excel.Worksheet activeWorksheet 
                = ((Excel.Worksheet)Globals.ExcelHBaseAddIn.Application.Worksheets[2]);
            activeWorksheet.Name = <span style="color: #a31515">"Frequency"</span>;
            Excel.Range navigator = activeWorksheet.get_Range(<span style="color: #a31515">"A1"</span>);
            <span style="color: green">// most of the fun stuff happens here</span>
            <span style="color: blue">int</span> numRows = MapReduce.executeMapReduce(navigator
                , <span style="color: blue">this</span>.filterColumn
                , <span style="color: blue">this</span>.filterValue
                , <span style="color: blue">this</span>.frequencyColumn
                , <span style="color: blue">this</span>.hostName.Text
                , <span style="color: blue">this</span>.tableName.Text);
            <span style="color: green">// autofit the range</span>
            Excel.Range c1 = activeWorksheet.Cells[1, 1];
            Excel.Range c2 = activeWorksheet.Cells[numRows, 2];
            <span style="color: blue">this</span>.cols = activeWorksheet.get_Range(c1, c2); 
            <span style="color: blue">this</span>.cols.EntireColumn.AutoFit();
            <span style="color: green">// bring the worksheet to the top</span>
            activeWorksheet.Activate();
        }</pre>
<p>All the work is done by the method <em>MapReduce.executeMapReduce()</em>, partially shown below. The .NET-to-Java method call, <em>HBaseToLinq.FrequencyMapRed.executeMapRed()</em>, is almost the same Java code used in the previous lab, <a title="lastProjectLink" href="http://www.jnbridge.com/jn/blog/2012/10/10/building-a-linq-provider-for-hbase-mapreduce/">Building a LINQ provider for HBase MapReduce</a>. The only modifications have been to remove hard-coded column names, instead using the programmatic column names for filtering and frequency counts chosen by the user. The method then scans the results of the MapReduce job stored in the table, <em>summary_user, </em>and loads them into a worksheet, returning the number of records in the results table.</p>
<pre style="font-family: Verdana;font-size: 11;color: black;background: white">            <span style="color: blue">try</span>
            {
                HBaseToLinq.FrequencyMapRed.executeMapRed(hostName
                    , tableName
                    , frequencyColumn
                    , columnToFilter
                    , filterValue);
            }
            <span style="color: blue">catch</span>(<span style="color: #2b91af">Exception</span> ex)
            {
                <span style="color: blue">throw</span> ex;
            }
            Configuration hbaseConfig = HBaseConfiguration.create();
            hbaseConfig.set(<span style="color: #a31515">"hbase.zookeeper.quorum"</span>, hostName);
            <span style="color: blue">try</span>
            {
                <span style="color: blue">string</span> cellName = 
                     frequencyColumn.Substring(frequencyColumn.IndexOf(<span style="color: #a31515">":"</span>) +1);
                <span style="color: blue">string</span> familyName = 
                     frequencyColumn.Substring(0, frequencyColumn.IndexOf(<span style="color: #a31515">":"</span>));
                HTable tbl = <span style="color: blue">new</span> HTable(hbaseConfig, <span style="color: #a31515">"summary_user"</span>);
                Scan scan = <span style="color: blue">new</span> Scan();
                ResultScanner scanner = tbl.getScanner(scan);
                Result r;
                <span style="color: blue">while</span> ((r = scanner.next()) != <span style="color: blue">null</span>)
                {
                    rowKey = Bytes.toString(r.getRow());
                    count = Bytes.toInt(r.getValue(Bytes.toBytes(familyName)
                         , Bytes.toBytes(<span style="color: #a31515">"total"</span>)));
                    currentCell = navigator.Cells[currentRow, currentColumn++];
                    currentCell.Value2 = rowKey;
                    currentCell = navigator.Cells[currentRow++, currentColumn];
                    currentCell.Value2 = count;
                    currentColumn = 1;
                }
                scanner.close();
                tbl.close();
            }
            <span style="color: blue">catch</span> (<span style="color: #2b91af">Exception</span> ex)
            {
                <span style="color: blue">throw</span> ex;
            }
            <span style="color: blue">return</span> currentRow - 1;</pre>
<p>Here&#8217;s a screen shot of the Excel add-in after performing the MapReduce.</p>
<p style="padding-left: 30px"><a href="http://www.jnbridge.com/jn/blog/2013/05/06/building-an-excel-add-in-for-hbase-mapreduce/addinmr/" rel="attachment wp-att-1671"><img class="alignnone  wp-image-1671" style="border: 1px solid black;margin-top: 4px;margin-bottom: 20px" src="http://www.jnbridge.com/jn/wp-content/blogs.dir/1/files/2013/03/AddInMR.jpg" alt="" width="556" height="470" /></a></p>
<h4>Visualizing data</h4>
<p>Data visualization through graphs and charts is an important final step when investigating and analyzing data. Clicking on the button <em>Chart Frequencies</em> causes the add-in to create a stacked column chart of the Frequency worksheet. Here&#8217;s the code for the handler, <em>onChartFrequenciesClick()</em>.</p>
<pre style="font-family: Verdana;font-size: 11;color: black;background: white">        <span style="color: blue">private</span> <span style="color: blue">void</span> onChartFrequenciesClick(<span style="color: blue">object</span> sender, <span style="color: #2b91af">EventArgs</span> e)
        {
            Excel.Workbook wb = Globals.ExcelHBaseAddIn.Application.ActiveWorkbook;
            Excel.Chart chart = (Excel.Chart)wb.Charts.Add();
            chart.ChartType = Excel.XlChartType.xlColumnStacked;
            chart.SetSourceData(<span style="color: blue">this</span>.cols, Excel.XlRowCol.xlColumns);
            chart.HasTitle = <span style="color: blue">true</span>;
            <span style="color: blue">string</span> filterName = <span style="color: blue">this</span>.filterColumn.Substring(<span style="color: blue">this</span>.filterColumn.IndexOf(<span style="color: #a31515">":"</span>) + 1);
            <span style="color: blue">string</span> frequencyName 
                 = <span style="color: blue">this</span>.frequencyColumn.Substring(<span style="color: blue">this</span>.frequencyColumn.IndexOf(<span style="color: #a31515">":"</span>) + 1);
            chart.ChartTitle.Text = <span style="color: #a31515">"Frequency of "</span> 
                  + frequencyName 
                  + <span style="color: #a31515">" when "</span> + filterName 
                  + <span style="color: #a31515">" = "</span> + <span style="color: blue">this</span>.filterValue;
        }</pre>
<p>This screen shot of the add-in shows the resulting chart. Notice that the MapReduce columns for filtering and frequency are different than the previous example. Here, the question being asked is &#8220;What is the frequency of visiting IP addresses for the page, /cats.html&#8221;.</p>
<p><a href="http://www.jnbridge.com/jn/blog/2013/05/06/building-an-excel-add-in-for-hbase-mapreduce/addinchart/" rel="attachment wp-att-1707"><img class="alignnone  wp-image-1707" style="border: 1px solid black;margin-top: 4px;margin-bottom: 20px;margin-left: 30px" src="http://www.jnbridge.com/jn/wp-content/blogs.dir/1/files/2013/03/AddInChart.jpg" alt="" width="579" height="452" /></a></p>
<h3>Conclusion</h3>
<p>Building an Excel add-in that supports viewing any HBase table of column families and provides filtering and Map Reduce frequency counts is relatively straightforward. Leveraging the HBase Java client APIs using JNBridgePro to create .NET proxies is key to the simplicity.  By keeping the MapReduce job both on the Java side and generic, any table can be filtered and reduced to frequencies of one particular column.</p>
<p>The source for this example can be downloaded <a title="download" href="http://www.jnbridge.com/labs/HBaseExcelAddIn.zip">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jnbridge.com/jn/blog/2013/05/06/building-an-excel-add-in-for-hbase-mapreduce/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JNBridge JMS Adapter for BizTalk Server supports BTS 2013</title>
		<link>http://www.jnbridge.com/jn/blog/2013/04/15/jnbridge-jms-adapter-for-biztalk-server-supports-bts-2013/</link>
		<comments>http://www.jnbridge.com/jn/blog/2013/04/15/jnbridge-jms-adapter-for-biztalk-server-supports-bts-2013/#comments</comments>
		<pubDate>Mon, 15 Apr 2013 18:22:35 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Adapters]]></category>
		<category><![CDATA[Announcements]]></category>
		<category><![CDATA[BizTalk Server]]></category>
		<category><![CDATA[Adapter]]></category>
		<category><![CDATA[BizTalk]]></category>
		<category><![CDATA[JMS]]></category>
		<category><![CDATA[jnbridge]]></category>

		<guid isPermaLink="false">http://www.jnbridge.com/jn/?p=1754</guid>
		<description><![CDATA[Microsoft has released BizTalk Server 2013, and the good news for users of our JMS adapter for BizTalk Server is that it already works with the new BTS release. Simply install and configure the adapter in exactly the same way as you did with earlier versions of BizTalk Server.  It just works!]]></description>
				<content:encoded><![CDATA[<p>Microsoft has released BizTalk Server 2013, and the good news for users of our JMS adapter for BizTalk Server is that it already works with the new BTS release.</p>
<p>Simply install and configure the adapter in exactly the same way as you did with earlier versions of BizTalk Server.  It just works!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jnbridge.com/jn/blog/2013/04/15/jnbridge-jms-adapter-for-biztalk-server-supports-bts-2013/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Announcing JNBridgePro 7.0</title>
		<link>http://www.jnbridge.com/jn/blog/2013/02/27/announcing-jnbridgepro-7-0/</link>
		<comments>http://www.jnbridge.com/jn/blog/2013/02/27/announcing-jnbridgepro-7-0/#comments</comments>
		<pubDate>Wed, 27 Feb 2013 07:17:31 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Announcements]]></category>
		<category><![CDATA[JNBridgePro]]></category>
		<category><![CDATA[Mono]]></category>
		<category><![CDATA[New releases]]></category>
		<category><![CDATA[Announcement]]></category>
		<category><![CDATA[new release]]></category>

		<guid isPermaLink="false">http://www.jnbridge.com/jn/?p=1594</guid>
		<description><![CDATA[Today we’re excited to announce JNBridgePro 7.0, with two new major features: support for Mono, and the elimination of “bitness” issues. These improvements will enable users to expand the reach of their applications, and simplify the development and deployment process. JNBridgePro 7.0 can now run on Mono One of the most common questions about JNBridgePro [...]]]></description>
				<content:encoded><![CDATA[<p>Today we’re excited to announce JNBridgePro 7.0, with two new major features: support for Mono, and the elimination of “bitness” issues. These improvements will enable users to expand the reach of their applications, and simplify the development and deployment process.</p>
<h2>JNBridgePro 7.0 can now run on Mono</h2>
<p>One of the most common questions about JNBridgePro that we’ve had to say no to is “Can it run on Mono?” Starting today with JNBridgePro 7.0, the answer is yes. As a user of JNBridgePro, you’ve created applications that combine .NET and Java code, where the .NET code runs on Windows machines, and the Java code runs in a JVM. Now with JNBridgePro 7.0, the .NET code can also run on Linux machines, using the Mono runtime. (As always, the Java sides of the applications can run on any platform that can run Java.)</p>
<p>Why use Mono? Here are four examples:</p>
<ol>
<li>You want to move your existing .NET &amp; Java application onto a commodity Linux server for business or technical reasons.
<p><a href="http://www.jnbridge.com/jn/blog/2013/02/27/announcing-jnbridgepro-7-0/move2linux-3/" rel="attachment wp-att-1618"><img class="alignleft size-full wp-image-1618" title="Move2Linux" src="http://www.jnbridge.com/jn/wp-content/blogs.dir/1/files/2013/02/Move2Linux2.png" alt="" width="602" height="232" /></a></p>
</li>
<li>You want to create greenfield applications on Linux platforms. In this example, you can build an application that combines an ASP.NET Web application with Java EE code running on an application server, and have the entire result run on a Linux server.
<p><a href="http://www.jnbridge.com/jn/blog/2013/02/27/announcing-jnbridgepro-7-0/monoaspdotnet-2/" rel="attachment wp-att-1633"><img src="http://www.jnbridge.com/jn/wp-content/blogs.dir/1/files/2013/02/MonoASPdotNET1.png" alt="" title="MonoASPdotNET" width="463" height="170" class="alignleft size-full wp-image-1633" /></a></p>
</li>
<li>You want to move your .NET &amp; Java application to a Linux-based IaaS cloud provider.
<p><a href="http://www.jnbridge.com/jn/blog/2013/02/27/announcing-jnbridgepro-7-0/move2linuxcloud/" rel="attachment wp-att-1630"><img src="http://www.jnbridge.com/jn/wp-content/blogs.dir/1/files/2013/02/Move2LinuxCloud.png" alt="" title="Move2LinuxCloud" width="516" height="257" class="alignleft size-full wp-image-1630" /></a></p>
</li>
<li>As an ISV, you want to expand your.NET&amp;Java application’s footprint beyond Windows to support for Linux:
<p><a href="http://www.jnbridge.com/jn/blog/2013/02/27/announcing-jnbridgepro-7-0/supportlinux/" rel="attachment wp-att-1627"><img src="http://www.jnbridge.com/jn/wp-content/blogs.dir/1/files/2013/02/SupportLinux.png" alt="" title="SupportLinux" width="365" height="340" class="alignleft size-full wp-image-1627" /></a></p>
</li>
</ol>
<p>No code changes are necessary to move your .NET &amp; Java applications that use JNBridgePro from Windows to Linux, just some possible configuration file changes, so your existing applications will just work.</p>
<p>JNBridgePro 7.0’s current Mono support is on Linux, on the Ubuntu, openSUSE, and Debian distributions currently supported by Mono, as well as on Windows. We’re considering extending JNBridgePro’s Mono support to additional platforms, based on customer feedback. JNBridgePro will work on Mono in both the .NET-to-Java and Java-to-.NET directions using the TCP/binary communications mechanism, and in the .NET-to-Java direction using the HTTP/SOAP communications mechanism. Future releases will fill in the gaps in available communications mechanisms, so you will be able to use any mechanism on any platform.</p>
<table class="pricing">
<tbody>
<tr>
<th></th>
<th>Microsoft .NET<br />
(Windows)</th>
<th>Mono<br />
(Linux, Windows)</th>
</tr>
<tr>
<td>.NET-to-Java</td>
<td>Shared memory</p>
<p>TCP/binary</p>
<p>HTTP/SOAP</td>
<td>TCP/binary</p>
<p>HTTP/SOAP</td>
</tr>
<tr>
<td>Java-to-.NET</td>
<td>Shared memory</p>
<p>TCP/binary</p>
<p>HTTP/SOAP</td>
<td>TCP/binary</td>
</tr>
</tbody>
</table>
<h2>Unified 32-bit and 64-bit</h2>
<p>Ever since we’ve introduced support for 64-bit platforms, customers have sometimes been confused by “bitness” issues. In JNBridgePro 7.0, we’ve eliminated bitness-related confusion by unifying our 32-bit and 64-bit distributions into a single release.</p>
<p>First, customers no longer need to decide ahead of time whether they need 32-bit or 64-bit JNBridgePro – now, there’s just a single installer containing the components and tools that will work for you regardless of whether you’re creating 32-bit or 64-bit applications. That means that there will be no more situations where you first download the 64-bit JNBridgePro installer, then need to go back and download the 32-bit version.</p>
<p>Second, you can now create “Any CPU” applications that work with the shared-memory communications mechanism. “Any CPU” applications will run as 64-bit processes on 64-bit systems, and as 32-bit processes on 32-bit systems. Since the JNBridgePro shared-memory components contain native code and come in 32-bit and 64-bit flavors, there used to be situations where users would create an “Any CPU” application using shared memory that ran fine on a 64-bit machine, but that threw an exception on a 32-bit machine (or vice versa). In such cases, the user would have to go back and create separate 32-bit and 64-bit builds using the proper shared memory components. Now, you can create a single “Any CPU” build that contains both the 32-bit and 64-bit shared memory components, and the correct ones will be used depending on the bitness of the currently-running process. This increases flexibility in deployment, speeds up the time spend building and testing, and eliminates potential errors.</p>
<h2>Download the new version</h2>
<p>JNBridgePro 7.0, with Mono support and unified 32/64-bit capabilities, is available for download now. Download it <a href="http://www.jnbridge.com/bin/downloads.php?pr=1&amp;id=0">here</a>, or check out the <a href="http://www.jnbridge.com/docs.htm">documentation</a> and our <a href="http://www.jnbridge.com/jnbp-examples.htm">demos and examples</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jnbridge.com/jn/blog/2013/02/27/announcing-jnbridgepro-7-0/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Follow-up to the Java update post</title>
		<link>http://www.jnbridge.com/jn/blog/2013/02/13/follow-up-to-the-java-update-post/</link>
		<comments>http://www.jnbridge.com/jn/blog/2013/02/13/follow-up-to-the-java-update-post/#comments</comments>
		<pubDate>Wed, 13 Feb 2013 09:00:33 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Commentary]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JNBridgePro]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Updates]]></category>

		<guid isPermaLink="false">http://www.jnbridge.com/jn/?p=1586</guid>
		<description><![CDATA[We had a great response to our recent post on Oracle&#8217;s new Java 7 auto-updates, their silent removal of Java 6, and the problems that can cause. We had coverage in The Register, InfoQ, and DZone. The Register article in particular had a great comment thread, and I urge you to check it out. At [...]]]></description>
				<content:encoded><![CDATA[<p>We had a great response to our recent post on Oracle&#8217;s new Java 7 auto-updates, their silent removal of Java 6, and the problems that can cause. We had coverage in <a href="http://www.theregister.co.uk/2013/01/31/java_security_update/">The Register</a>, <a href="http://www.infoq.com/news/2013/01/jdk6-retirement">InfoQ</a>, and <a href="http://java.dzone.com/articles/dzone-links-you-dont-want-miss-3">DZone</a>. The Register article in particular had a <a href="http://forums.theregister.co.uk/forum/1/2013/01/31/java_security_update/">great comment thread</a>, and I urge you to check it out.</p>
<p>At the end of that thread, I wrote a response to several points that were brought up, and I thought I&#8217;d post a version of that response here.</p>
<p><em>Why not just support Java 7 and be done with it? Why make people use Java 6?</em></p>
<p>Our product does handle Java 7 (and 6, and 5, etc  &#8212; our stuff works with Java back to 1.3.1, although we&#8217;ll probably move that up to Java 5 in the next release) just fine.  But it&#8217;s a tool that customers use to run and deploy their own software &#8212; it allows .NET code to communicate with Java code.  The Java runs in its own JVM, and the users get to choose whichever JRE they want &#8212; it can be any version, it can be 32-bit or 64-bit.  It can be from just about any vendor.  That&#8217;s a good thing, because our users have their own environments, and it&#8217;s their own business &#8212; we don&#8217;t dictate or judge.  So, the problem isn&#8217;t ours (we&#8217;re not making people use Java 6 &#8212; but our customers might choose to use Java 6), except that our customers&#8217; problems become our problems, and then we have to scramble.  But it bothers me when we have to scramble to solve a problem that really wasn&#8217;t caused by us, and which really shouldn&#8217;t have been a problem to begin with.</p>
<p><em>Why not just get version of the latest installed Java from the registry and use that?</em></p>
<p>The problem is that that only tells us what Java is on the machine &#8212; it doesn&#8217;t tell us what Java the user wants or needs.  Again, we let the user make that decision &#8212; checking the registry won&#8217;t tell us what we want to know.  (Nor will JAVA_HOME, as someone else suggested.)</p>
<p><em>Why would an enterprise user allow auto-updates, when unexpected things can clearly happen?</em></p>
<p>The short answer is that they shouldn&#8217;t.  But clearly it happens &#8212; it happened to the customers of our customer.  (Our customer is an ISV that uses our product.  Their customers are the end users.)  And when it happened, our customer heard about it from their customer, and called us, and we had to scramble, and the problem was easily corrected, but it shouldn&#8217;t have been a problem in the first place.</p>
<p><em>Why not just supply the jvm.dll?</em></p>
<p>First, because it should be up to our users to determine which version they need &#8212; we can handle just about any one chosen and don&#8217;t dictate.  Second, because jvm.dll doesn&#8217;t work in isolation and we&#8217;d have to supply an entire private JRE &#8212; it&#8217;s much more than a single file.</p>
<p>Finally, I just want to point out that in our case, the problem is just the validity of a file path &#8212; Java 6 and Java 7 reside in different places, and a single path won&#8217;t work with both.  However, the comment thread on The Register&#8217;s article has certainly come up with plenty of examples of Java software that works with Java 6 that simply won&#8217;t work with Java 7, so for other users this is a much bigger issue than just an invalid file path.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jnbridge.com/jn/blog/2013/02/13/follow-up-to-the-java-update-post/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java 7 update “silently” deletes Java 6, breaks applications</title>
		<link>http://www.jnbridge.com/jn/blog/2013/01/28/java-7-update-silently-deletes-java-6-breaks-applications/</link>
		<comments>http://www.jnbridge.com/jn/blog/2013/01/28/java-7-update-silently-deletes-java-6-breaks-applications/#comments</comments>
		<pubDate>Mon, 28 Jan 2013 09:00:32 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Commentary]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Tips and examples]]></category>
		<category><![CDATA[JNBridgePro]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Updates]]></category>

		<guid isPermaLink="false">http://www.jnbridge.com/jn/?p=1549</guid>
		<description><![CDATA[Software updates shouldn’t do unexpected things. They particularly shouldn’t remove software other than what they’re ostensibly updating, and they shouldn’t break running applications. It’s even worse when this all happens automatically and without warning. The other day, one of our customers, an ISV that uses JNBridgePro in one of their applications that includes both Java [...]]]></description>
				<content:encoded><![CDATA[<p>Software updates shouldn’t do unexpected things. They particularly shouldn’t remove software other than what they’re ostensibly updating, and they shouldn’t break running applications. It’s even worse when this all happens automatically and without warning.</p>
<p>The other day, one of our customers, an ISV that uses JNBridgePro in one of their applications that includes both Java and .NET, told us that several of their customers had reported that their applications stopped working after the customers updated their installations of Java 7. The strange thing is that the applications didn’t use Java 7; they used Java 6. The problem was fixed by reconfiguring JNBridgePro on those machines to point to Java 7 rather than Java 6. Our customer asked us whether JNBridgePro had problems with this update, or with Java 7. We answered that there should be no problem: JNBridgePro works fine with both Java 6 and Java 7, including the latest updates.</p>
<p>Something odd was going on, so we started digging deeper. Running the auto-installer for the new Java 7 update, we saw the following screen, with the relevant message buried in it:</p>
<p><a href="http://www.jnbridge.com/jn/blog/2013/01/28/java-7-update-silently-deletes-java-6-breaks-applications/javainstaller-3/" rel="attachment wp-att-1573"><img src="http://www.jnbridge.com/jn/wp-content/blogs.dir/1/files/2013/01/javaInstaller2.png" alt="" title="javaInstaller" width="407" height="304" class="alignnone size-full wp-image-1573" /></a></p>
<p>Then we found the <a href="http://www.oracle.com/technetwork/java/javase/documentation/autoupdate-1667051.html">following notice on the Oracle website</a>:</p>
<blockquote>
<p><b>About the Java 6 Auto-Update to Java 7</b></p>
<p>Oracle will start auto-updating Windows 32-bit, Java Runtime Environment (JRE) users from JRE 6 to JRE 7 in December 2012.</p>
<p>The Java auto-update mechanism is designed to keep Java users up-to-date with the latest security fixes. <i>To achieve this goal Windows users that rely on Java’s auto-update mechanism will have their JRE 6 replaced with JRE 7.</i></p>
<p>In December 2012 Oracle will start to auto-update a sample of users from JRE 6 to JRE 7 to evaluate the auto-update mechanism, user experience and seamless migration. Oracle will then start auto-updating all Windows 32-bit users from JRE 6 to JRE 7 with the update release of Java, Java SE 7 Update 11 (Java SE 7u11), due in February 2013.</p>
<ul>
<li>JRE 7 has been the default version on Java.com since April 2012 and is now being used by millions of users.</li>
<li>As we did when JRE 5 was replaced by JRE 6, <i>we will auto-update users of the older release to the newer version of Java</i>.</li>
<li>As always, all users are encouraged to update to the most recent Java versions available for public download.</li>
<li>In February 2011 Oracle announced the End of Public Updates for their Java SE 6 products for July 2012. In February 2012 Oracle extended the End of Public Updates for 4 months, to November 2012. See:
<ul>
<li><a href="http://www.oracle.com/technetwork/java/javase/eol-135779.html">Oracle Java SE Support Roadmap</a></li>
<li><a href="https://blogs.oracle.com/henrik/entry/updated_java_6_eol_date">Updated Java 6 End of Public Updates Date</a></li>
</ul>
</li>
<p>• Oracle is now extending the End of Public Updates again for 4 additional months to provide developers and users with additional time to migrate to Java 7. The last publicly available release of Java 6 will be in February of 2013 with the release of Java SE 6 Update 39 (Java SE 6u39).
</ul>
<p><a href="https://blogs.oracle.com/henrik/entry/java_6_eol_h_h">Java 6 End of Public Updates extended to February 2013</a></p>
</blockquote>
<p>(Emphasis ours.)</p>
<p>This is absolutely astonishing. Oracle has decided that, in order to fix extensively-reported security problems, they will not only update Java 7 (their latest version of Java), <b><i>they will also completely delete a completely separate product</i></b>. Yes, Java 6 is a separate product from Java 7. They can be installed side-by-side, and many users have both Java 6 and Java 7 installed on their machines. Some of their applications depend on Java 6, and others might depend on Java 7, and these dependencies are typically hard-coded or configured to point to the correct, and different, file locations. Can you imagine if Microsoft released an update to .NET 4.0 that also removed .NET 2.0? This is just as serious.</p>
<p>Worse, it appears that they are taking it upon themselves to replace installations of Java 6 with Java 7 <b><i>even if the users have only Java 6 on their machines</i></b>.</p>
<p>How is this different from, say, Microsoft updating Office by replacing one version by another? That’s an update-in-place, so hard-coded paths will often still work. Even so, updating one version of Office to another likely won’t involve an auto-update, but rather an explicit re-installation, and one would expect dependencies to break. Java 6 and 7, on the other hand, are side-by-side installations, and one doesn’t expect an update to one to affect the other in any way.</p>
<p>Let’s look at this from Oracle’s point of view. The security holes that they plugged in Java 7 likely also exist in Java 6, and they have stopped providing new updates to Java 6. Why not replace Java 6 with Java 7 and fix these problems?</p>
<p>This strategy might make sense for less sophisticated users who only use Java inside their browsers. They likely do not know which version of Java they have, or even if they Java at all. In this case, it makes sense to fix the problem by updating the Java installations, so that machines aren’t infected with malware by visiting rogue websites.</p>
<p>However, most of our customers aren’t using Java in their browsers. Their Java is running on servers, or in self-contained desktop applications that, if they connect to the Internet, only connect to specific sites. Their applications depend on specific versions of Java, or on Java files being in specific places. JNBridgePro’s shared memory mechanism, in particular, depends on an absolute path to a specific jvm.dll, but that’s not the only case where dependencies like this occur. With their update, Oracle has silently pulled the rug out from under many running applications.</p>
<p>Why do I say “silently”? Even though the update installer mentions that Java 6 “might” be removed, and the notice on the website says it “will” be removed, very few people will read the text in the installer; they will likely just click through it, since nobody expects a Java 7 updater to remove Java 6. And almost nobody will read the notice on the website unless they are specifically searching for it.</p>
<p>One could say that IT shops should turn off automatic updates, and apply updates in a controlled process after extensive testing. That’s true, but clearly auto-updates can still happen; it’s not reasonable to assume that all business users have sufficient IT support. After all, it happened to our customer’s customers. It’s also the case that a situation like Java 6 being removed in a Java 7 update might not be found in a controlled test, since most such tests will only try to see whether applications that use Java 7 will be affected. To make matters more difficult, the mechanism for turning off automatic Java updates isn’t obvious.</p>
<p>If you find yourself with a broken application that uses JNBridgePro and Java 6 after updating Java 7, here’s what you can do:</p>
<ul>
<li>You can reconfigure your application (and particularly the JNBridgePro component) to use Java 7 rather than Java 6. JNBridgePro will have absolutely no problem with Java 7. Whether your Java code will work with Java 7 is something that you will need to determine yourself.</li>
<li>You can go to the <a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">Oracle Java website</a> and download and reinstall Java 6. Then, you’ll be back where you were.</li>
</ul>
<p>Finally, you should strongly consider turning off automatic Java updates. As I said it isn’t immediately obvious how to do this, since the Java control panel, by default, doesn’t display the Update tab that contains the switch that turns off updating. The Update tab only appears when the control panel is run as administrator. You can turn off the auto-update switch as follows:</p>
<ol>
<li>In Windows Explorer, navigate to your JRE’s bin folder (for example, C:\Program Files (x86)\Java\jre7\bin, although it might be different on your machine).</li>
<li>Once you’re there, find javacpl.exe. Right-click on it, and select “Run as administrator.”</li>
<li>Inside the control panel, you can now see the Update tab. Select it, then uncheck the “Check for Updates Automatically” checkbox.</li>
</ol>
<p><a href="http://www.jnbridge.com/jn/blog/2013/01/28/java-7-update-silently-deletes-java-6-breaks-applications/javacontrolpanel-2/" rel="attachment wp-att-1570"><img src="http://www.jnbridge.com/jn/wp-content/blogs.dir/1/files/2013/01/javaControlPanel1.png" alt="" title="javaControlPanel" width="440" height="476" class="alignnone size-full wp-image-1570" /></a></p>
<p>The control panel will ask if you really want to do this. Trust me, you do. Then click on the OK button.</p>
<p>Note that if you do this, it’s your responsibility to make sure that your Java installations are up to date, and that you engage in good security practices. You will need to keep track of the latest Java security problems and the latest updates when they become available, and you can <a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">download them from Oracle’s Java site</a>. The downloaded updaters will only update the specific Java versions, and they won’t pull the rug out from under you by removing completely different versions of Java that your software might depend on.</p>
<p>In summary, Oracle’s latest automatic Java update is dangerous and irresponsible because it “silently” removes software other than the software it ostensibly updates, thereby breaking running code. By all means update and secure the Java running inside browsers, but leave our server and desktop software alone.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jnbridge.com/jn/blog/2013/01/28/java-7-update-silently-deletes-java-6-breaks-applications/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Looking to the future</title>
		<link>http://www.jnbridge.com/jn/blog/2012/12/07/looking-to-the-future/</link>
		<comments>http://www.jnbridge.com/jn/blog/2012/12/07/looking-to-the-future/#comments</comments>
		<pubDate>Fri, 07 Dec 2012 09:00:55 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Celebrating 10 Years]]></category>
		<category><![CDATA[Feedback]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[future]]></category>
		<category><![CDATA[interoperability]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[JNBridgePro]]></category>
		<category><![CDATA[Metro]]></category>
		<category><![CDATA[Mobility]]></category>
		<category><![CDATA[Mono]]></category>
		<category><![CDATA[Node.js]]></category>
		<category><![CDATA[Non-Java JVM languages]]></category>
		<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[System Center Operations Manager]]></category>
		<category><![CDATA[VSTO]]></category>
		<category><![CDATA[Windows Phone 8]]></category>
		<category><![CDATA[WinRT]]></category>

		<guid isPermaLink="false">http://www.jnbridge.com/jn/?p=1535</guid>
		<description><![CDATA[Our tenth anniversary festivities will soon be drawing to a close. Past installments on this blog have looked toward the past or the present, and now we’d like to spend a little bit of time thinking about the future. Specifically, where do you think we should take JNBridge next? There are lots of scenarios where [...]]]></description>
				<content:encoded><![CDATA[<p>Our tenth anniversary festivities will soon be drawing to a close. Past installments on this blog have looked toward the past or the present, and now we’d like to spend a little bit of time thinking about the future.</p>
<p>Specifically, where do you think we should take JNBridge next? There are lots of scenarios where we can potentially apply JNBridgePro interoperability technologies, but we’d like to learn more about interoperability challenges you are facing, or new technologies that you might be using in the future that could present obstacles to interoperability. Here’s a list of technologies where we could conceivably extend the JNBridge footprint. Are these scenarios that might be of interest to you?</p>
<ul>
<li><em><strong>Metro and WinRT:</strong></em> Are you thinking about writing Metro or WinRT apps that need to call Java? How about Java apps that need to access Metro/WinRT DLLs or Portable Class Libraries?</li>
<p/>
<li><em><strong>Mono:</strong></em> Would you like to write Mono applications that call Java libraries, or Java applications that call .NET code running on Mono? Would the Mono be running on Windows, Linux, Mac OS X, or some other platform?</li>
<p/>
<li><em><strong>Mobility:</strong></em> There are lots of possible scenarios here:</li>
<p/>
<ul>
<li><em>Windows Phone 8:</em> Are you considering writing WP8 apps that might call Java libraries? Would you want that Java to reside on a server, or on the phone?</li>
<p/>
<li><em>Android:</em> How about calling .NET libraries from Android’s Java? Or calling Java libraries from .NET/Mono running on Android?</li>
<p/>
<li><em>iOS:</em> Is there any kind of interoperability scenario involving iOS that you’re considering?</li>
<p/>
</ul>
<li><em><strong>JVM-based dynamic languages:</strong></em> In a <a href="http://www.jnbridge.com/jn/blog/2012/11/14/groovy-to-net-integration/">previous blog post</a>, we talked about Groovy-to-.NET integration, and how it just works. Are there other interoperability scenarios involving dynamic languages that you’d like to see?</li>
<p/>
<li><em><strong>JavaScript and Node.js:</strong></em> JavaScript is a different platform than Java, but that doesn’t mean that there isn’t a place for JNBridgePro-style integration. Do you have any prospective projects involving integration between JavaScript or Node.js and .NET?</li>
<p/>
<li><em><strong>Additional Microsoft products:</strong></em> Our BizTalk adapter for JMS is very popular, but it’s not the only Microsoft product where JNBridge technologies could be used for interoperability. Are you thinking of integrating Java code with SharePoint? System Center Operations Manager? Visual Studio Tools for Office (VSTO)? Windows Azure?</li>
</ul>
<p><em>The sky’s the limit:</em> Any other interoperability scenarios you’d like to see us tackle? Please drop us a note, either to <a href="mailto:info@jnbridge.com">info@jnbridge.com</a> or in the (moderated) comments below.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jnbridge.com/jn/blog/2012/12/07/looking-to-the-future/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Groovy-to-.NET integration</title>
		<link>http://www.jnbridge.com/jn/blog/2012/11/14/groovy-to-net-integration/</link>
		<comments>http://www.jnbridge.com/jn/blog/2012/11/14/groovy-to-net-integration/#comments</comments>
		<pubDate>Wed, 14 Nov 2012 18:40:59 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Tips and examples]]></category>
		<category><![CDATA[dynamic languages]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[JNBridgePro]]></category>
		<category><![CDATA[JRuby]]></category>
		<category><![CDATA[Jython]]></category>
		<category><![CDATA[Non-Java JVM languages]]></category>
		<category><![CDATA[Scala]]></category>

		<guid isPermaLink="false">http://www.jnbridge.com/jn/?p=1527</guid>
		<description><![CDATA[Lately, much of the action in the Java world has been in the development and use of non-Java languages that run on the JVM. That’s why we were pleased to hear from a customer who wanted to use JNBridgePro to call .NET assemblies from code written in Groovy. For those of you unaware, Groovy is [...]]]></description>
				<content:encoded><![CDATA[<p>Lately, much of the action in the Java world has been in the development and use of non-Java languages that run on the JVM. That’s why we were pleased to hear from a customer who wanted to use JNBridgePro to call .NET assemblies from code written in Groovy.</p>
<p>For those of you unaware, <a href="http://groovy.codehaus.org/">Groovy</a> is a dynamic language that runs on the JVM. Groovy classes compile to Java binary .class files, and Groovy code can call (and be called from) any conventional Java class. In our customer’s case, they wanted to call .NET classes from Groovy, which really meant calling proxies. Since proxied .NET classes are just Java classes, everything should just work, and it did.</p>
<p>It’s really easy to illustrate how this is done. Let’s assume we have a very simple test class written in C#:</p>
<p>namespace GroovyTestDotNetSide<br />
{<br />
&nbsp;&nbsp;&nbsp;public class SimpleObject<br />
&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public SimpleObject(int i)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(&#8220;In SimpleObject.ctor: value supplied is &#8221; + i);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;}<br />
}</p>
<p>First, we proxy it and generate a proxy jar file proxies.jar. Now, if we create a Groovy project and include proxies.jar in the build classpath, along with jnbcore.jar, bcel-5.1-jnbridge.jar (all of which would be included in any Java-to-.NET project using JNBridgePro), and groovy-all-1.7.5.jar (or something similar, depending on which version of Groovy is being used), we can write Groovy code to instantiate SimpleObject:</p>
<p>import GroovyTestDotNetSide.SimpleObject<br />
import com.jnbridge.jnbcore.DotNetSide</p>
<p>class SimpleTest {</p>
<p>&nbsp;&nbsp;&nbsp;static main(args) {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// set up JNBridge<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DotNetSide.init(args[0])</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def simpleObject = new SimpleObject(3)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;println &#8220;Done!&#8221;<br />
&nbsp;&nbsp;&nbsp;}<br />
}</p>
<p>&nbsp;</p>
<p>Just as in a conventional Java-to-.NET project, you need to initialize the Java side through a call to DotNetSide.init(), supplying the path to the Java-side properties file, or an equivalent Properties object. Once that is done, you can make any valid call to a proxy. In this case, we instantiate SimpleObject, but we can also call static or instance methods of SimpleObject, or access SimpleObject fields or properties or events.</p>
<p>Once the project is build, you will have a binary file SimpleTest.class, and you can run the application in the usual way (assuming all the jar, .class, and .properties files are in the current folder):</p>
<p>java -cp &#8220;proxies.jar;jnbcore.jar;bcel-5.1-jnbridge.jar;groovy-all-1.7.5.jar;. &#8221; SimpleTest props.properties</p>
<p>The properties file can configure for tcp/binary, http/soap, or shared memory; if you are using tcp/binary or http/soap, you will or course need to run a properly configured .NET side.</p>
<p>As you can see, this just works in exactly the same way you’d expect if you were using Java.</p>
<p>While we have not yet tried it, interoperability with Groovy should also work in the .NET-to-Groovy direction. Similarly, JNBridgePro should also work when integrating .NET with other JVM-based languages like Scala, JRuby, and Jython.</p>
<p>Are you thinking about using JNBridgePro with JVM-based languages other than Java? If so, let us know in the comments or by sending us email at <a href="mailto:info@jnbridge.com">info@jnbridge.com</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jnbridge.com/jn/blog/2012/11/14/groovy-to-net-integration/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Build 2012 Recap</title>
		<link>http://www.jnbridge.com/jn/blog/2012/11/07/build-2012-recap/</link>
		<comments>http://www.jnbridge.com/jn/blog/2012/11/07/build-2012-recap/#comments</comments>
		<pubDate>Wed, 07 Nov 2012 09:00:04 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Events]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[Build]]></category>
		<category><![CDATA[Hadoop]]></category>
		<category><![CDATA[JNBridgePro]]></category>
		<category><![CDATA[Windows 8]]></category>
		<category><![CDATA[Windows Phone 8]]></category>

		<guid isPermaLink="false">http://www.jnbridge.com/jn/?p=1520</guid>
		<description><![CDATA[We were in Redmond last week for the Build conference, where Microsoft offered deep dives into their latest technologies. Unlike last year, where the emphasis was on in-depth looks at lower-level technologies like Windows RT, .NET 4.5, and Windows 8 internals, this year’s conference concentrated on higher-level application-oriented APIs like Microsoft Account (formerly Windows Live [...]]]></description>
				<content:encoded><![CDATA[<p>We were in Redmond last week for the Build conference, where Microsoft offered deep dives into their latest technologies. Unlike last year, where the emphasis was on in-depth looks at lower-level technologies like Windows RT, .NET 4.5, and Windows 8 internals, this year’s conference concentrated on higher-level application-oriented APIs like Microsoft Account (formerly Windows Live ID) and Windows Store, as well as more peripheral (to us) technologies like Windows Phone 8. In fact, if we had seen the list of sessions in advance, we might have decided to skip the conference and watch any relevant sessions online (although it was nice to receive the Surface RT, Nokia Lumia 920, and 100GB of SkyDrive capacity that all attendees received). Even so, there were a number of interesting sessions that were relevant to our work on interoperability. (All Build sessions can be seen here: <a href="http://channel9.msdn.com/events/build/2012">http://channel9.msdn.com/events/build/2012</a>.)</p>
<p>There was an <a href="http://channel9.msdn.com/Events/Build/2012/3-038">interesting session</a> that unveiled details of Microsoft’s previously announced Hadoop on Windows Azure offering (now called HDInsight). Since the offering has been by invitation only, there haven’t been too many details. It’s interesting to contrast Microsoft’s approach to Hadoop/.NET integration, which uses .NET streaming but conceals it with the artful use of wrappers, with our approach of direct API calls through JNBridgePro (<a href="http://www.jnbridge.com/jn/blog/2012/05/18/creating-net-based-mappers-and-reducers-for-hadoop-with-jnbridgepro">here </a>and <a href="http://www.jnbridge.com/jn/blog/2012/10/10/building-a-linq-provider-for-hbase-mapreduce">here</a>). Each approach can be useful in certain situations.</p>
<p><a href="http://channel9.msdn.com/Events/Build/2012/2-011">Microsoft offered more details on their new Windows Azure Virtual Machines</a>, which brings to Windows Azure the capabilities already found in Amazon’s EC2. Microsoft claims advantages over Amazon’s offerings, particularly in the areas of administration and automation. For us and for our users, this is interesting because it makes it even easier to create applications that use JNBridgePro and deploy them to Windows Azure. It had been possible, but there were a number of complexities in setting up and starting the applications in the cloud; now it’s as easy in Windows Azure as it’s already been with Amazon EC2. In addition, Microsoft will be offering virtual machine images containing BizTalk Server 2010 R2 CTP, and you will be able to use JNBridge’s JMS adapter for BTS with those images.</p>
<p><a href="http://channel9.msdn.com/Events/Build/2012/3-016">A talk on the evolution of .NET</a> covered both the history of the platform, including all of the earlier milestones, and possible future directions in which the platform can go. The speaker made the very interesting point that the typical PC of 1998 (when the .NET project began) or even 2000 (when it was unveiled) is very different from the typical PC of today, in terms of processing power, memory and storage, user interface, and connectivity, and any future .NET implementations will need to reflect that. We can only wonder what that will entail, but it’s encouraging to learn that Microsoft still considers .NET to be an essential platform for their future offerings.</p>
<p>One of the more surprising things <a href="http://channel9.msdn.com/Events/Build/2012/3-005">we learned had to do with Windows Phone 8</a>, which we really hadn’t been tracking, since it didn’t seem relevant to our mission. Windows Phone 8’s runtime is actually a version of the .NET CLR called CoreCLR, which is really based on the existing SilverLight CLR. We haven’t supported SilverLight, both because of its slow adoption, and because it has been constrained in what it can do, but we were interested to learn that in response to requests from developers, the CoreCLR will allow Windows Phone 8 applications to access existing native (read C++) gaming engines. Since Java Runtime Environments are also native C++ libraries, does that mean that a JVM can be hosted in a Windows Phone 8 app’s process? If so, it might be possible to support shared memory interoperability in Windows Phone 8 applications. It’s certainly something we’ll be looking into. Will it be possible to do something similar in Windows 8 “Metro” apps? That remains to be seen.</p>
<p>Did you attend Build, or watch sessions online? If so, did you see something that you’d like to call our attention to? If so, please let us know in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jnbridge.com/jn/blog/2012/11/07/build-2012-recap/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building a LINQ provider for HBase MapReduce</title>
		<link>http://www.jnbridge.com/jn/blog/2012/10/10/building-a-linq-provider-for-hbase-mapreduce/</link>
		<comments>http://www.jnbridge.com/jn/blog/2012/10/10/building-a-linq-provider-for-hbase-mapreduce/#comments</comments>
		<pubDate>Wed, 10 Oct 2012 07:05:52 +0000</pubDate>
		<dc:creator>William Heinzman</dc:creator>
				<category><![CDATA[Labs]]></category>
		<category><![CDATA[Hadoop]]></category>
		<category><![CDATA[HBase]]></category>
		<category><![CDATA[LINQ]]></category>

		<guid isPermaLink="false">http://www.jnbridge.com/jn/?p=1280</guid>
		<description><![CDATA[Summary HBase is a distributed, scalable, big data storage and retrieval system developed as part of the Apache Hadoop project. As a Java framework, HBase applications must use Java APIs, resulting in single-platform solutions. Cross-platform solutions, particularly those that provide front-end data query, analysis and presentation, like Microsoft Excel, or query languages like LINQ, the [...]]]></description>
				<content:encoded><![CDATA[<h3>Summary</h3>
<p><em>HBase is a distributed, scalable, big data storage and retrieval system developed as part of the Apache Hadoop project. As a Java framework, HBase applications must use Java APIs, resulting in single-platform solutions. Cross-platform solutions, particularly those that provide front-end data query, analysis and presentation, like Microsoft Excel, or query languages like LINQ, the .NET Language Integrated Query framework, are currently not supported.</em></p>
<p><em>This latest project from JNBridge Labs explores building a simple .NET LINQ provider for HBase using the Java API for creating, managing and scanning HBase tables and the .NET LINQ provider interfaces. In addition, the project investigates LINQ support for HBase MapReduce jobs written in Java by adding an extension to the LINQ query syntax. </em></p>
<p><em>By continuing the research into Hadoop and .NET interoperability introduced in the previous project, <a title="LastHadoopLab" href="http://www.jnbridge.com/jn/blog/2012/05/18/creating-net-based-mappers-and-reducers-for-hadoop-with-jnbridgepro/#.UHN9P5g70uc">Creating .NET-based Mappers and Reducers for Hadoop</a>, JNBridge Labs champions interoperability between Windows and <span style="text-decoration: underline;">any</span> Java solution running on <span style="text-decoration: underline;">any</span> system. The potential of products like DryadLINQ—canceled when Microsoft shelved the Dryad HPC project in favor of Hadoop—is still relevant, but only if that potential isn’t constrained to Hadoop running on particular systems. Microsoft’s port of Hadoop from Linux to Azure and Windows Server is single-system. Interoperability between Hadoop and LINQ or Excel  means supporting Hadoop on any system.</em></p>
<h3>Introduction</h3>
<p>Apache HBase is a <em>big table</em> implementation using the Apache Hadoop platform. Hadoop, in addition to providing distributed, parallel processing of petabyte-size data-sets, also provides the distributed file system, HDFS, where HBase tables are stored. An HBase table is a distributed, multi-dimensional sorted map containing structured data. A web access record is the obvious canonical example:</p>
<p style="padding-left: 30px;">125.125.125.125 &#8211;  [10/Oct/2011:21:15:05 +0500] &#8220;GET /index.html HTTP/1.0&#8243; 200 1043 &#8221;http://www.ibm.com/&#8221; &#8220;Mozilla/4.05 [en] (WinNT; I)&#8221;</p>
<p>While the above record can be thought of as a row with several columns, the point is that it&#8217;s in a single table; there&#8217;s no relationship to other tables because there are no other tables. Nor is there a need to worry about indexes. Designing efficient schema that enable efficient queries isn&#8217;t the point. That&#8217;s because a row isn&#8217;t an object like an employee or a bank account, it&#8217;s a single datum and only has value as part of a data set, which can have several million rows. The queries one makes to these tables tend to be reductions to simple statistics, i.e. sums. In other words, we&#8217;re talking  brute-force, something that Apache Hadoop, MapReduce algorithms and parallel processing make straight-forward and fast.</p>
<p>LINQ, or Language INtegrated Query, is a Microsoft .NET  feature that provides query capabilities in the .NET languages. Actually, it&#8217;s syntactic sugar around the set of static query extensions defined in the class <em>System.Linq.Enumerable</em> that can be used to query any .NET collection of objects that implement <em>IEnumerable&lt;T&gt;. </em>LINQ is also extendable; it&#8217;s possible to implement a LINQ provider for just about anything as long as there&#8217;s a convenient abstraction that allows queries. In the case of HBase, a LINQ provider makes perfect sense.</p>
<p>This current offering from JNBridge Labs will explore building a simple LINQ provider for HBase using the HBase client Java API for creating, managing and scanning tables. In addition, the LINQ provider will also support  HBase MapReduce jobs written in Java using the HBase table mapper/reducer templates and Hadoop. This differs from the previous Hadoop lab that demonstrated using mappers and reducers written in .NET, but called by the MapReduce Job on the Java-side.</p>
<h3>Getting Started</h3>
<p>Here are the components required for the lab. Also, some important links, resources and configuration tips.</p>
<h4>Apache Hadoop stack</h4>
<p>The first requirement is access to a Hadoop/HBase implementation. Installing and configuring Hadoop and HBase can be an exercise, particularly if the platform is Windows rather than Linux. The best option is to download the free Linux <a title="clouderaVM" href="https://ccp.cloudera.com/display/SUPPORT/Cloudera%27s+Hadoop+Demo+VM+for+CDH4" target="_blank">virtual images</a> from Cloudera. The VM runs CentOS 5.8 and contains Cloudera&#8217;s distribution of the entire Apache Hadoop stack already installed and configured. While it&#8217;s not truly distributed among many machines, each component of the Hadoop stack runs as a separate process, so it&#8217;s possible to add more worker nodes. The VM is available for VMWare, KVM and VirtualBox. Make sure that the VM&#8217;s access to the internet is bridged, <em>do not use NAT</em>. Also, because Java server applications running on Linux are notoriously finicky when it comes to DNS and the loop-back interface, make sure to modify the <em>/etc/hosts</em> file on the Linux and Windows machines. This will ensure that the HBase client API can actually connect to the Hadoop/HBase implementation through ZooKeeper.</p>
<p>On the Linux VM, remove the loopback IP address, 127.0.0.1, replacing it with the IP address of the VM, then recycle the VM.</p>
<p style="padding-left: 30px;"># 127.0.0.1          localhost.localdomain localhost<br />
192.168.1.3          localhost.localdomain localhost</p>
<p>On the Windows development machine, add this to the hosts file (\Windows\System32\drivers\etc\hosts):</p>
<p style="padding-left: 30px;">192.168.1.3           localhost.localdomain</p>
<h4>Development machine</h4>
<p>Visual Studio 2010, Eclipse Juno and, of course, JNBridgePro 6.1. JNBridgePro will be used to build .NET proxies of the HBase client API as well as a Java class that implements MapReduce. This will enable calling Java from the .NET code that implements the LINQ provider.</p>
<h3>Calling Java from .NET: Creating proxies using JNBridgePro</h3>
<p>Since the LINQ provider is written in C#/.NET and needs to call a Java class API, the first step is to use the JNBridgePro plug-in for Visual Studio to create an assembly of proxies that represent the Java API. When a proxy of a Java class is instantiated in .NET, the real Java object is instantiated in the Java Virtual Machine. The JNBridgePro run-time manages communications, i.e. invoking methods, and syncing garbage collection between the .NET CLR and the JVM.</p>
<p>For this development step, as well as during run-time, a bunch of Hadoop, HBase and ZooKeeper JAR files must be available on the Windows machine. While these can be obtained by downloading the zip archives from the Apache project, it&#8217;s best to use the JAR files from the Cloudera distribution, thus avoiding version-itis. These can be scraped from the VM (look in <em>/usr/lib/hadoop/lib</em>, <em>/usr/lib/hbase/lib</em>, etc.)</p>
<p>This is a screen shot of the <em>Edit Class Path</em> dialog for the JNBridgePro Visual Studio plug-in.</p>
<p style="padding-left: 30px;"><a href="http://www.jnbridge.com/jn/blog/2012/10/10/building-a-linq-provider-for-hbase-mapreduce/editclasspath/" rel="attachment wp-att-1301"><img class="wp-image-1301 alignnone" style="margin-top: 15px; margin-bottom: 15px;" src="http://www.jnbridge.com/jn/wp-content/blogs.dir/1/files/2012/10/EditClassPath.jpg" alt="" width="365" height="278" /></a></p>
<p>These are the JAR files required to create the .NET proxies. During run-time, three additional JAR files must be included in the JVM&#8217;s class path when initiating the bridge between the JVM and the CLR: <em>avro-1.5.4.jar</em>, <em>commons-httpclient-3.1.jar</em> and <em>slf4j-nop-1.6.1.jar</em> (the last JAR file inhibits logging by Hadoop and HBase. If you&#8217;re interested in the volume of information logged during a MapReduce computation, just remove this JAR file from the class path).</p>
<p>This is a screen shot of the JNBridgePro proxy tool in Visual Studio. The left hand pane shows all the namespaces found in the JAR files shown in the above dialog. The required namespaces are <em>org.apache.hadoop.hbase.client</em> and <em>org.apache.hadoop.hbase.filter</em>. In addition, individual classes like <em>org.apache.hadoop.hbase.HBaseConfiguration</em> are required (see the link at the end of this blog to download the source).</p>
<p style="padding-left: 30px;"> <a href="http://www.jnbridge.com/jn/blog/2012/10/10/building-a-linq-provider-for-hbase-mapreduce/proxytool/" rel="attachment wp-att-1306"><img class="alignnone  wp-image-1306" style="border: 1px solid black; margin-top: 4px; margin-bottom: 20px;" src="http://www.jnbridge.com/jn/wp-content/blogs.dir/1/files/2012/10/proxytool.jpg" alt="" width="602" height="265" /></a></p>
<p>By clicking on the <strong>Add+</strong> button, the chosen classes, as well as every dependent class, will be found and displayed in the center pane. The right-hand pane displays the public members and methods of the Java <em>HTable</em> class. The last step is to build the proxy assembly, <em>HBaseProxies.dll</em>.</p>
<h3>Creating and populating an HBase Table</h3>
<p>It would be nice to have an HBase table loaded with data and provide an opportunity to test calling various HBase Java APIs from .NET. To keep things simple—after all, this is an example—the data will consist of an IP address, like &#8220;88.240.129.183&#8243; and the requested web page, for example &#8220;/zebra.html&#8221;. The code for creating and populating the table, shown below, is in the project, <em>LoadData</em>.</p>
<pre style="font-family: Arial; font-size: 12px; color: black; background-color: white; padding-left: 30px;"><span style="color: blue;">using</span> org.apache.hadoop.hbase;
<span style="color: blue;">using</span> org.apache.hadoop.hbase.client;
<span style="color: blue;">using</span> org.apache.hadoop.hbase.util;
<span style="color: blue;">using</span> org.apache.hadoop.conf;</pre>
<pre style="font-family: Arial; font-size: 12px; color: black; background-color: white; padding-left: 30px;">com.jnbridge.jnbproxy.<span style="color: #2b91af;">JNBRemotingConfiguration</span>.specifyRemotingConfiguration(
                    com.jnbridge.jnbproxy.<span style="color: #2b91af;">JavaScheme</span>.sharedmem
                    , <span style="color: #a31515;">@"C:\Program Files\Java\jre6\bin\client\jvm.dll"</span>
                    , <span style="color: #a31515;">@"C:\Program Files\JNBridge\JNBridgePro v6.1\jnbcore\jnbcore.jar"</span>
                    , <span style="color: #a31515;">@"C:\Program Files\JNBridge\JNBridgePro v6.1\jnbcore\bcel-5.1-jnbridge.jar"</span>
                    , <span style="color: #a31515;">@"C:\HBase\jars\cdh4Jars\zookeeper-3.4.3-cdh4.0.0.jar;..."</span>);

<span style="color: #2b91af;">Configuration</span> hbaseConfig = <span style="color: #2b91af;">HBaseConfiguration</span>.create();
hbaseConfig.set(<span style="color: #a31515;">"hbase.zookeeper.quorum"</span>, <span style="color: #a31515;">"192.168.1.3"</span>);
<span style="color: #2b91af;">HBaseAdmin</span> admin = <span style="color: blue;">new</span> <span style="color: #2b91af;">HBaseAdmin</span>(hbaseConfig);
<span style="color: #2b91af;">HTableDescriptor</span> desc = <span style="color: blue;">new</span> <span style="color: #2b91af;">HTableDescriptor</span>(<span style="color: #a31515;">"access_logs"</span>);
desc.addFamily(<span style="color: blue;">new</span> <span style="color: #2b91af;">HColumnDescriptor</span>(<span style="color: #a31515;">"details"</span>));
admin.createTable(desc);
<span style="color: #2b91af;">HTable</span> htable = <span style="color: blue;">new</span> <span style="color: #2b91af;">HTable</span>(hbaseConfig, <span style="color: #a31515;">"access_logs"</span>);
htable.setAutoFlush(<span style="color: blue;">false</span>);
htable.setWriteBufferSize(1024 * 1024 * 12);
<span style="color: blue;">int</span> totalRecords = 100000;
<span style="color: #2b91af;">Random</span> rand = <span style="color: blue;">new</span> <span style="color: #2b91af;">Random</span>();
<span style="color: blue;">string</span>[] pages = { <span style="color: #a31515;">"/dogs.html"</span>, <span style="color: #a31515;">"/cats.html"</span>, <span style="color: #a31515;">"/rats.html"</span>, <span style="color: #a31515;">"/bats.html"</span>, <span style="color: #a31515;">"/zebras.html"</span>
                        , <span style="color: #a31515;">"/t-rex.html"</span>, <span style="color: #a31515;">"/lizard.html"</span>, <span style="color: #a31515;">"/birds.html"</span>, <span style="color: #a31515;">"/beetles.html"</span>, <span style="color: #a31515;">"/elephants.html"</span>};
<span style="color: blue;">string</span>[] ipAdrs = { <span style="color: #a31515;">"88.240.129.183"</span>, <span style="color: #a31515;">"144.122.180.55"</span>, <span style="color: #a31515;">"85.100.75.104"</span>, <span style="color: #a31515;">"78.34.27.101"</span>
                        , <span style="color: #a31515;">"23.121.45.220"</span>, <span style="color: #a31515;">"206.27.34.178"</span>, <span style="color: #a31515;">"174.82.96.35"</span>, <span style="color: #a31515;">"13.234.26.45"</span>
                        , <span style="color: #a31515;">"245.213.200.10"</span>, <span style="color: #a31515;">"167.38.92.14"</span>, <span style="color: #a31515;">"27.98.32.45"</span>, <span style="color: #a31515;">"22.48.92.13"</span> };
<span style="color: blue;">for</span> (<span style="color: blue;">int</span> i = 0; i &lt; totalRecords; i++)
{
    <span style="color: #2b91af;">Put</span> put = <span style="color: blue;">new</span> <span style="color: #2b91af;">Put</span>(<span style="color: #2b91af;">Bytes</span>.toBytes(i));
    put.add(<span style="color: #2b91af;">Bytes</span>.toBytes(<span style="color: #a31515;">"details"</span>), <span style="color: #2b91af;">Bytes</span>.toBytes(<span style="color: #a31515;">"ip"</span>)
            , <span style="color: #2b91af;">Bytes</span>.toBytes(ipAdrs[rand.Next(ipAdrs.Length)]));
    put.add(<span style="color: #2b91af;">Bytes</span>.toBytes(<span style="color: #a31515;">"details"</span>), <span style="color: #2b91af;">Bytes</span>.toBytes(<span style="color: #a31515;">"page"</span>)
            , <span style="color: #2b91af;">Bytes</span>.toBytes(pages[rand.Next(pages.Length)]));
    htable.put(put);
}
htable.flushCommits();
htable.close();</pre>
<p>The above C# code uses the type &#8216;sbyte&#8217;, not &#8216;byte&#8217;. That&#8217;s because the Java type &#8216;byte&#8217; is signed, in .NET it&#8217;s unsigned. Since this is .NET calling a Java method, the proxies return type &#8216;sbyte&#8217;. Bringing up the HBase shell on the Linux VM, we can dump the first row of the HBase table, <em>access_logs</em>.</p>
<p style="padding-left: 30px;"><a href="http://www.jnbridge.com/jn/blog/2012/10/10/building-a-linq-provider-for-hbase-mapreduce/showrow1/" rel="attachment wp-att-1336"><img class="alignnone  wp-image-1336" style="margin-top: 10px; margin-bottom: 20px;" src="http://www.jnbridge.com/jn/wp-content/blogs.dir/1/files/2012/10/showrow1.jpg" alt="" width="581" height="143" /></a></p>
<p>The row is comprised of two cells, <em>ip</em> and <em>page</em>, both grouped under a column, <em>details</em>. A column is a semantic grouping of cells, hence the use of the term &#8216;family&#8217; that prevails. The hex numbers on the left, both zero, are the index to the first row. The timestamp allows a third dimension, providing queries based on a time span.</p>
<h3>Building a custom LINQ Provider</h3>
<p>LINQ, in its simplest form, is a set of extension methods to the generic interface <em>IEnumerable&lt;T&gt;</em>. Consider the following class, really no more than a structure:</p>
<pre style="font-family: Arial; font-size: 12px; color: black; background-color: white; padding-left: 30px;"><span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">AccessRecord </span>{
    <span style="color: green;">// Properties.</span>
    <span style="color: blue;">public</span> <span style="color: blue;">string</span> ipAddress { <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }
    <span style="color: blue;">public</span> <span style="color: blue;">string</span> page { <span style="color: blue;">get</span>; <span style="color: blue;">set</span>; }       
    <span style="color: green;">// Constructor.</span>
    <span style="color: blue;">internal</span> AccessRecord(<span style="color: blue;">string</span> ip, <span style="color: blue;">string</span> page) {
        <span style="color: blue;">this</span>.ipAddress = ip;
        <span style="color: blue;">this</span>.page = page;
    }
}</pre>
<p>A collection of AccessRecord instances using the generic <em>List&lt;T&gt; </em>template, which inherits from IEnumerable&lt;T&gt;, can be queried using the static extension methods defined in the class <em>System.Linq.Enumerable</em>. For example, consider determining the frequency—the count—of the pages requested by a given IP address.</p>
<pre style="font-family: Arial; font-size: 12px; color: black; background-color: white; padding-left: 30px;"><span style="color: #2b91af;">List</span>&lt;<span style="color: #2b91af;">AccessRecord</span>&gt; lst = <span style="color: blue;">new</span> <span style="color: #2b91af;">List</span>&lt;<span style="color: #2b91af;">AccessRecord</span>&gt;();
<span style="color: blue;">var</span> query1 = lst.Where(rec =&gt; rec.ipAddress == <span style="color: #a31515;">"88.240.129.183"</span>).OrderBy(rec =&gt; rec.page)
             .GroupBy(rec =&gt; rec.page)
             .Select(grps =&gt; <span style="color: blue;">new</span> {ip = grps.Key, count = grps.Count()});</pre>
<p>Alternatively, using the syntactic sugar in C#, the query can be stated in this form.</p>
<pre style="font-family: Arial; font-size: 12px; color: black; background-color: white; padding-left: 30px;"><span style="color: blue;">var</span> query1 = <span style="color: blue;">from</span> rec <span style="color: blue;">in</span> records
             <span style="color: blue;">where</span> rec.ipAddress == <span style="color: #a31515;">"88.240.129.183"</span>
             <span style="color: blue;">orderby</span> rec.page
             <span style="color: blue;">group</span> rec <span style="color: blue;">by</span> rec.page <span style="color: blue;">into</span> grps
             <span style="color: blue;">select</span> <span style="color: blue;">new</span> { ip = grps.Key, count = grps.Count() };</pre>
<p>While this is pretty cool, it will not scale well. The list of access records could number 10,000,000. Moreover, there&#8217;s the overhead of building the initial data structure in the first place. That&#8217;s why LINQ supplies a framework for building custom query providers. The entire point is to have both the data and the query computations happen someplace else, like HBase.</p>
<h4>Implementing <em>IOrderedQueryable&lt;T&gt;</em> and <em>IQueryProvider</em></h4>
<p>A LINQ provider requires implementing two interfaces: <em>IQueryProvider</em> and either <em>IQueryable&lt;T&gt;</em> or <em>IOrderedQueryable&lt;T&gt;. </em>If the LINQ provider needs to support the <em>OrderBy</em> and <em>ThenBy</em> query operators, then the IOrderedQueryable interface must be implemented (actually, because IOrderedQueryable inherits from IQueryable, all three interfaces must be implemented).</p>
<p>The implementation of IOrderedQueryable&lt;T&gt; can be found in the class, <em>QueryableHBaseData</em>. The important method in this class is the implementation of <em>IEnumerable&lt;T&gt;.GetEnumerator()</em>. Consider the code that displays the results of the above queries by <em>enumerating</em> over the returned collection.</p>
<pre style="font-family: Arial; font-size: 12px; color: black; background-color: white; padding-left: 30px;"><span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> pg <span style="color: blue;">in</span> query1)
{
    <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"     page: "</span> + pg.ip + <span style="color: #a31515;">" "</span> + pg.count);
}</pre>
<p>The actual query is executed when the  GetEnumerator() method is called on the instance of QueryableHBaseData.</p>
<pre style="font-family: Arial; font-size: 12px; color: black; background-color: white; padding-left: 30px;"><span style="color: blue;">public</span> <span style="color: #2b91af;">IQueryProvider</span> Provider { <span style="color: blue;">get</span>; <span style="color: blue;">private</span> <span style="color: blue;">set</span>; }
<span style="color: blue;">public</span> <span style="color: #2b91af;">Expression</span> Expression { <span style="color: blue;">get</span>; <span style="color: blue;">private</span> <span style="color: blue;">set</span>; }

<span style="color: blue;">public</span> <span style="color: #2b91af;">IEnumerator</span>&lt;TData&gt; GetEnumerator()
{
    <span style="color: blue;">return</span> (Provider.Execute&lt;<span style="color: #2b91af;">IEnumerable</span>&lt;TData&gt;&gt;(Expression)).GetEnumerator();
}</pre>
<p>The <em>Provider</em> property is the implementation of IQueryProvider, which can be found in the class, <em>HBaseQueryProvider</em>. The <em>Expression</em> property is the query to be executed. The <em>HBaseQueryProvider.Execute()</em> method is responsible for executing the query. So far, all of this is straight forward. The hard part in implementing a LINQ provider is parsing, walking and decorating an expression tree represented by an instance of <em>System.Linq.Expressions.Expression. </em></p>
<h4>The innermost-where expression</h4>
<p>The reason for walking the expression tree is to find the innermost w<em>here </em>expression. A <em>where</em> operator is a filter—it&#8217;s what makes a query, well, a query. Most custom LINQ providers find the <em>innermost-where</em> expression and partially evaluate the lambda expression argument to retrieve the filter predicate values. The predicate values, as well as some other information, is used to query the real data source and return the results as a collection of <em>IQueryable&lt;T&gt;. </em>The expression tree is then rewritten, essentially replacing the original data source with the collection of IQueryable objects that now resides in memory. The new expression tree is then re-executed using the HBaseQueryProvider class. All of this is implemented in the method <em>HBaseQueryContext.Execute()</em>.</p>
<pre style="font-family: Arial; font-size: 12px; color: black; background-color: white; padding-left: 30px;"><span style="color: blue;">internal</span> <span style="color: blue;">static</span> <span style="color: blue;">object</span> Execute(<span style="color: #2b91af;">Expression</span> expression, <span style="color: blue;">bool</span> IsEnumerable)
{
    <span style="color: green;">// Find the call to Where() and get the lambda expression predicate.</span>
    <span style="color: #2b91af;">InnermostWhereFinder</span> whereFinder = <span style="color: blue;">new</span> <span style="color: #2b91af;">InnermostWhereFinder</span>();
    <span style="color: #2b91af;">MethodCallExpression</span> whereExpression = whereFinder.GetInnermostWhere(expression);
    <span style="color: #2b91af;">LambdaExpression</span> lambdaExpression = 
             (<span style="color: #2b91af;">LambdaExpression</span>)((<span style="color: #2b91af;">UnaryExpression</span>)(whereExpression.Arguments[1])).Operand;
    <span style="color: green;">// Send the lambda expression through the partial evaluator.</span>
    lambdaExpression = (<span style="color: #2b91af;">LambdaExpression</span>)<span style="color: #2b91af;">Evaluator</span>.PartialEval(lambdaExpression);
    <span style="color: green;">// Get the column name(s)</span>
    <span style="color: #2b91af;">ColumnFinder</span> cf = <span style="color: blue;">new</span> <span style="color: #2b91af;">ColumnFinder</span>(lambdaExpression.Body);
    <span style="color: #2b91af;">List</span>&lt;<span style="color: blue;">string</span>&gt; columns = cf.Columns;  
    <span style="color: green;">// Call HBase and get the results.</span>
    <span style="color: #2b91af;">AccessRecord</span>[] records = <span style="color: #2b91af;">HBaseHelper</span>.GetColumnsFromHBase(
             columns.First&lt;<span style="color: blue;">string</span>&gt;()
             , cf.IsIP, cf.IsPage);    
    <span style="color: #2b91af;">IQueryable</span>&lt;<span style="color: #2b91af;">AccessRecord</span>&gt; queryableRecords = records.AsQueryable&lt;<span style="color: #2b91af;">AccessRecord</span>&gt;();
    <span style="color: green;">// Copy the expression tree that was passed in, changing only the first</span>
    <span style="color: green;">// argument of the innermost MethodCallExpression.</span>
    <span style="color: #2b91af;">ExpressionTreeModifier</span> treeCopier = <span style="color: blue;">new</span> <span style="color: #2b91af;">ExpressionTreeModifier</span>(queryableRecords);
    <span style="color: #2b91af;">Expression</span> newExpressionTree = treeCopier.CopyAndModify(expression);
    <span style="color: blue;">if</span> (IsEnumerable)
        <span style="color: blue;">return</span> queryableRecords.Provider.CreateQuery(newExpressionTree);
    <span style="color: blue;">else</span>
        <span style="color: blue;">return</span> queryableRecords.Provider.Execute(newExpressionTree);
}</pre>
<p>The class <em>ColumnFinder </em>takes the lambda expression that represents the predicate to the where operator and returns the right hand side of the predicate expression, in our example <em>record.ip == &#8220;88.240.129.183&#8243;</em>. The left hand side of the predicate expression, the field to test against, is obtained through the properties <em>ColumnFinder.IsIP</em> and <em>ColumnFinder.IsPage</em>. In keeping with the above example queries, this data is used to call <em>HBaseHelper.GetColumnsFromHBase()</em> with arguments 88.240.129.183, true and false.</p>
<h4>Scanning and filtering an HBase table</h4>
<p>Now that all the boring stuff is done, we can make some calls to the  HBase client Java API from .NET using the proxy assembly. The call to <em>HBaseHelper.GetColumnsFromHBase() </em>results in calling this code.</p>
<pre style="font-family: Arial; font-size: 12px; color: black; background-color: white; padding-left: 30px;"><span style="color: blue;">using</span> org.apache.hadoop.hbase;
<span style="color: blue;">using</span> org.apache.hadoop.hbase.client;
<span style="color: blue;">using</span> org.apache.hadoop.hbase.util;
<span style="color: blue;">using</span> org.apache.hadoop.io;
<span style="color: blue;">using</span> org.apache.hadoop.conf;
<span style="color: blue;">using</span> org.apache.hadoop.hbase.filter;</pre>
<pre style="font-family: Arial; font-size: 12px; color: black; background-color: white; padding-left: 30px;"><span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: #2b91af;">AccessRecord</span>[] hbaseColumnScan(<span style="color: blue;">string</span> column, <span style="color: blue;">bool</span> isIP, <span style="color: blue;">bool</span> isPage)
{
    <span style="color: #2b91af;">HTable</span> tbl = <span style="color: blue;">null</span>;
    <span style="color: #2b91af;">Scan</span> scn = <span style="color: blue;">null</span>;
    <span style="color: #2b91af;">SingleColumnValueFilter</span> svcFilter = <span style="color: blue;">null</span>;
    <span style="color: #2b91af;">ResultScanner</span> rs = <span style="color: blue;">null</span>;
    <span style="color: blue;">string</span> pg = <span style="color: blue;">null</span>;
    <span style="color: #2b91af;">Configuration</span> hbaseConfig = <span style="color: #2b91af;">HBaseConfiguration</span>.create();
    hbaseConfig.set(<span style="color: #a31515;">"hbase.zookeeper.quorum"</span>, <span style="color: #a31515;">"192.168.1.3"</span>);
    <span style="color: blue;">try</span>
    {
        tbl = <span style="color: blue;">new</span> <span style="color: #2b91af;">HTable</span>(hbaseConfig, <span style="color: #a31515;">"access_logs"</span>);
        scn = <span style="color: blue;">new</span> <span style="color: #2b91af;">Scan</span>();
        scn.setCaching(500);
        <span style="color: blue;">sbyte</span>[] scanColumn = <span style="color: blue;">null</span>;
        <span style="color: blue;">if</span> ( isIP )
            scanColumn = ipCol;
        <span style="color: blue;">else</span> <span style="color: blue;">if</span> ( isPage )
            scanColumn = pageCol;         
        svcFilter = <span style="color: blue;">new</span> <span style="color: #2b91af;">SingleColumnValueFilter</span>(family
            , scanColumn
            , <span style="color: #2b91af;">CompareFilter</span>.<span style="color: #2b91af;">CompareOp</span>.EQUAL
            , <span style="color: #2b91af;">Bytes</span>.toBytes(column));
        scn.setFilter(svcFilter);
        rs = tbl.getScanner(scn);
    }
    <span style="color: blue;">catch</span> (<span style="color: #2b91af;">Exception</span> ex)
    {
        <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"Unable to perform  column scan: "</span> + ex.Message);
    }
    <span style="color: #2b91af;">List</span>&lt;<span style="color: #2b91af;">AccessRecord</span>&gt; records = <span style="color: blue;">new</span> <span style="color: #2b91af;">List</span>&lt;<span style="color: #2b91af;">AccessRecord</span>&gt;();
    <span style="color: blue;">for</span> (<span style="color: #2b91af;">Result</span> r = rs.next(); r != <span style="color: blue;">null</span>; r = rs.next())
    {
        pg = <span style="color: #2b91af;">Bytes</span>.toString(r.getValue(family, pageCol));
        records.Add(<span style="color: blue;">new</span> <span style="color: #2b91af;">AccessRecord</span>(column, pg));
    }
    rs.close();
    tbl.close();
    <span style="color: blue;">return</span> records.ToArray&lt;<span style="color: #2b91af;">AccessRecord</span>&gt;();
}</pre>
<h4 style="font-family: Verdana; font-size: 12; color: black; background: white;">Testing the LINQ provider</h4>
<p>Here&#8217;s the example query using the HBase LINQ provider.</p>
<pre style="font-family: Arial; font-size: 12px; color: black; background-color: white; padding-left: 30px;"><span style="color: #2b91af;">QueryableHBaseData</span>&lt;<span style="color: #2b91af;">AccessRecord</span>&gt; records = 
               <span style="color: blue;"> new</span> <span style="color: #2b91af;">QueryableHBaseData</span>&lt;<span style="color: #2b91af;">AccessRecord</span>&gt;();</pre>
<pre style="font-family: Arial; font-size: 12px; color: black; background-color: white; padding-left: 30px;"><span style="color: blue;">var</span> query1 = <span style="color: blue;">from</span> record <span style="color: blue;">in</span> records
                <span style="color: blue;">where</span> record.ipAddress == <span style="color: #a31515;">"88.240.129.183"</span>
                <span style="color: blue;">orderby</span> record.page
                <span style="color: blue;">group</span> record <span style="color: blue;">by</span> record.page <span style="color: blue;">into</span> grps
                <span style="color: blue;">select</span> <span style="color: blue;">new</span> { ip = grps.Key, count = grps.Count() };

<span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"  IP address 88.240.129.183 visted these pages"</span>);
<span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> pg <span style="color: blue;">in</span> query1)
{
    <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"     page: "</span> + pg.ip + <span style="color: #a31515;">" "</span> + pg.count);
}</pre>
<p>This query scans the HBase table for all records where the IP address equals 88.240.129.183. However, in order to sort the requested pages, then group and count them, the query uses the standard Enumerable extensions against an array in memory. Considering the potential size of the results from a simple table scan, the current approach of implementing only the innermost-where operator is probably inefficient. It also doesn&#8217;t make use of MapReduce, almost the whole point in using HBase, especially considering that the example query is tailor-made for MapReduce.</p>
<h3>Using MapReduce in a LINQ query</h3>
<p>Since the LINQ provider is already calling Java, it should be simple to write a MapReduce implementation in Java using the HBase table mapper and reducer classes. It also gives us an excuse to write some Java code.</p>
<pre style="font-family: Arial; font-size: 12px; color: black; background-color: white; padding-left: 30px;"><span style="color: #993300;">public class</span> FrequencyMapRed {

    <span style="color: #993300;">private static final byte</span>[] <span style="color: #3e3ec1;"><em>family</em></span> = Bytes.toBytes(<span style="color: #3366ff;">"details"</span>);
    <span style="color: #993300;">private static final byte</span>[]<span style="color: #3e3ec1;"> <em>ipCol</em></span> = Bytes.toBytes(<span style="color: #3366ff;">"ip"</span>);
    <span style="color: #993300;">private static final byte</span>[] <span style="color: #3e3ec1;"><em>pageCol</em></span> = Bytes.toBytes(<span style="color: #3366ff;">"page"</span>);

    <span style="color: #993300;">static class</span> Mapper1 <span style="color: #993300;">extends</span> TableMapper&lt;Text, IntWritable&gt; 
    {
       <span style="color: #993300;"> private static final</span> IntWritable <em>one</em> = <span style="color: #993300;">new</span> IntWritable(1);
        <span style="color: #993300;">private</span> Text<span style="color: #3e3ec1;"> txt</span> = <span style="color: #993300;">new</span> Text();  
        <span style="color: #999999;">@Override</span>
       <span style="color: #993300;"> public void</span> map(ImmutableBytesWritable row, Result values, Context context)
                <span style="color: #993300;"> throws</span> IOException 
        {<span style="color: darkgreen;">      </span>
           String val = <span style="color: #993300;">new</span> String(values.getValue(<span style="color: #3e3ec1;"><em>family</em></span>, <span style="color: #3e3ec1;"><em>pageCol</em></span>));
            <span style="color: #3e3ec1;">txt</span>.set(val);
            <span style="color: #993300;">try</span> {
                context.write(<span style="color: #3e3ec1;">txt</span>, <em><span style="color: #3e3ec1;">one</span></em>);
            } <span style="color: #993300;">catch</span> (InterruptedException e) {
                <span style="color: #993300;">throw new</span> IOException(e);
            }
        }
    }

    <span style="color: #993300;">public static class</span> Reducer1 <span style="color: #993300;">extends</span> TableReducer&lt;Text, IntWritable, ImmutableBytesWritable&gt; 
    {
        <span style="color: #993300;">public void</span> reduce(Text key, Iterable&lt;IntWritable&gt; values, Context context)
                <span style="color: #993300;">throws</span> IOException, InterruptedException 
        {
            <span style="color: #993300;">int</span> sum = 0;
            <span style="color: #993300;">for</span> (IntWritable val : values) {
                sum += val.get();
            }
            Put put = <span style="color: #993300;">new</span> Put(Bytes.toBytes(key.toString()));
            put.add(<span style="color: #3e3ec1;"><em>family</em></span>, Bytes.toBytes<span style="color: #0000ff;">(<span style="color: #3366ff;">"total"</span></span>), Bytes.toBytes(sum));
            context.write(<span style="color: #993300;">null</span>, put);
        }
    }

    <span style="color: #993300;">public static void</span> executeMapRed(String columnToCount
           , String filterColumn
           , String filterColumnValue) 
               <span style="color: #993300;">throws</span> Exception
    { 
        Configuration conf = HBaseConfiguration.create();
        conf.set(<span style="color: #3366ff;">"hbase.zookeeper.quorum"</span>, <span style="color: #3366ff;">"localhost.localdomain"</span>);
        Job job = <span style="color: #993300;">null</span>;
        <span style="color: #993300;">try </span>{
	        job = <span style="color: #993300;">new</span> Job(conf, <span style="color: #3366ff;">"Hbase_FreqCounter1"</span>);
	        job.setJarByClass(FrequencyMapRed.class);
	        Scan scan = <span style="color: #993300;">new</span> Scan();
	        scan.setCaching(500);        
	        scan.setCacheBlocks(<span style="color: #993300;">false</span>);
	        SingleColumnValueFilter svcFilter = <span style="color: #993300;">new</span> SingleColumnValueFilter(<span style="color: #3e3ec1;"><em>family</em></span>
	                , Bytes.toBytes(filterColumn)
	                , CompareFilter.CompareOp.<span style="color: #3e3ec1;"><em>EQUAL</em></span>
	                , Bytes.toBytes(filterColumnValue));
	        scan.setFilter(svcFilter);
	        TableMapReduceUtil.initTableMapperJob(<span style="color: #3366ff;">"access_logs"</span>, scan, Mapper1.<span style="color: #993300;">class</span>, Text.<span style="color: #993300;">class</span>,
	                IntWritable.<span style="color: #993300;">class</span>, job);
	        TableMapReduceUtil.initTableReducerJob(<span style="color: #3366ff;">"summary"</span>, Reducer1.<span style="color: #993300;">class</span>, job);
	        job.waitForCompletion(<span style="color: #993300;">true</span>);
        }
        <span style="color: #993300;">catch</span> (Exception ex) {
        	<span style="color: #993300;">throw</span> ex;
	}  
    }
}</pre>
<p>Notice that the results of the MapReduce computation are placed in a table called <em>summary. </em>The table is created once and reused to hold results each time the MapReduce code executes. This table must be created using the HBase shell. <a href="http://www.jnbridge.com/jn/blog/2012/10/10/building-a-linq-provider-for-hbase-mapreduce/createsum/" rel="attachment wp-att-1395"><img class="alignnone  wp-image-1395" style="margin-top: 10px; margin-bottom: 20px;" src="http://www.jnbridge.com/jn/wp-content/blogs.dir/1/files/2012/10/createsum.jpg" alt="" width="601" height="104" /></a></p>
<h4>Adding the Java MapReduce to the proxy assembly</h4>
<p>The above class can be archived to a JAR file, <em>FrequencyMapRed.jar</em>. Since the method FrequencyMapRed.executeMapRed() must be called from .NET, the JAR file needs to be added to the class path in the JNBridgePro Visual Studio plug-in. The class can be added to the proxy assembly by using the <em>Add Classes from Classpath</em> dialog. Once the proxy assembly is rebuilt, the new Java method that implements the MapReduce frequency computation can be called from .NET.</p>
<h3>Modifying the LINQ provider to support MapReduce</h3>
<p>The above MapReduce frequency implementation provides the same result as three LINQ query operators: <em>Where</em>, <em>OrderBy</em> and <em>GroupBy</em>. The innermost-where strategy did not implement the <em>OrderBy</em> and <em>GroupBy</em> operators. Trying to shoe-horn MapReduce to standard query operators is problematic. The problem is solved by optimizing the query into a graph of MapReduce jobs. Some query optimizers for big data implementations do exactly that, but for the scope of this example, it would be simpler to add a new query operator called <em>frequency</em>. Adding a new extension to IEnumerable is easy. The problem is that it would only be available when using the method call form of the query, i.e. <em>Where().Frequency().Select()</em>. It would not be available using the query form because C# doesn&#8217;t supply the syntax. However, the query form does support invoking delegates. Using this strategy leads to the following code found in the source file, <em>LinqFrequency.cs</em>.</p>
<pre style="font-family: Arial; font-size: 12px; color: black; background-color: white; padding-left: 30px;"><span style="color: blue;">public</span> <span style="color: blue;">class</span> <span style="color: #2b91af;">HBase</span>
{
    <span style="color: blue;">static</span> <span style="color: blue;">public</span> Func&lt;<span style="color: #2b91af;">AccessRecord</span>, <span style="color: #2b91af;">IEnumerable</span>&lt;<span style="color: #2b91af;">KeyValuePair</span>&lt;<span style="color: blue;">string</span>, <span style="color: blue;">int</span>&gt;&gt;&gt; frequency 
                    = MyFrequency;</pre>
<pre style="font-family: Arial; font-size: 12px; color: black; background-color: white; padding-left: 30px;">    <span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: #2b91af;">IEnumerable</span>&lt;<span style="color: #2b91af;">KeyValuePair</span>&lt;<span style="color: blue;">string</span>, <span style="color: blue;">int</span>&gt;&gt; MyFrequency(<span style="color: #2b91af;">AccessRecord</span> recs)
    {
        <span style="color: #2b91af;">IEnumerable</span>&lt;<span style="color: #2b91af;">KeyValuePair</span>&lt;<span style="color: blue;">string</span>, <span style="color: blue;">int</span>&gt;&gt; results = <span style="color: blue;">null</span>;
        <span style="color: blue;">try</span>
        {
            results = executeMapReduce(
                     (recs.page == <span style="color: #a31515;">"ip"</span> ? <span style="color: #a31515;">"page"</span> : <span style="color: #a31515;">"ip"</span>)
                     , recs.page, recs.ipAddress);
        }
        <span style="color: blue;">catch</span> (<span style="color: #2b91af;">Exception</span> ex)
        {
            <span style="color: #2b91af;">Console</span>.WriteLine(ex.Message);
        }
        <span style="color: blue;">return</span> results;
    }

    <span style="color: blue;">public</span> <span style="color: blue;">static</span> <span style="color: #2b91af;">IEnumerable</span>&lt;<span style="color: #2b91af;">KeyValuePair</span>&lt;<span style="color: blue;">string</span>, <span style="color: blue;">int</span>&gt;&gt; executeMapReduce(
                         <span style="color: blue;"> string</span> frequencyForThisCol
                        , <span style="color: blue;">string</span> filterThisCol
                        , <span style="color: blue;">string</span> withThisValue)
    {
        <span style="color: blue;">try</span>
        {
            <span style="color: #2b91af;">FrequencyMapRed</span>.executeMapRed(frequencyForThisCol, filterThisCol, withThisValue);
        }
        <span style="color: blue;">catch</span> (<span style="color: #2b91af;">Exception</span> ex)
        {
            <span style="color: blue;">throw</span> ex;
        }
        <span style="color: #2b91af;">Configuration</span> hbaseConfig = <span style="color: #2b91af;">HBaseConfiguration</span>.create();
        hbaseConfig.set(<span style="color: #a31515;">"hbase.zookeeper.quorum"</span>, <span style="color: #a31515;">"192.168.1.3"</span>);
        <span style="color: #2b91af;">HTable</span> htable = <span style="color: blue;">new</span> <span style="color: #2b91af;">HTable</span>(hbaseConfig, <span style="color: #a31515;">"summary"</span>);
        <span style="color: #2b91af;">Scan</span> scan = <span style="color: blue;">new</span> <span style="color: #2b91af;">Scan</span>();
        <span style="color: #2b91af;">ResultScanner</span> scanner = htable.getScanner(scan);
        <span style="color: #2b91af;">Result</span> r;
        <span style="color: blue;">string</span> page;
        <span style="color: blue;">int</span> count;
        <span style="color: #2b91af;">List</span>&lt;<span style="color: #2b91af;">KeyValuePair</span>&lt;<span style="color: blue;">string</span>, <span style="color: blue;">int</span>&gt;&gt; results = <span style="color: blue;">new</span> <span style="color: #2b91af;">List</span>&lt;<span style="color: #2b91af;">KeyValuePair</span>&lt;<span style="color: blue;">string</span>, <span style="color: blue;">int</span>&gt;&gt;();
        <span style="color: blue;">for</span> (r = scanner.next(); r != <span style="color: blue;">null</span>; r = scanner.next())
        {
            page = <span style="color: #2b91af;">Bytes</span>.toString(r.getRow());
            count = <span style="color: #2b91af;">Bytes</span>.toInt(r.getValue(<span style="color: #2b91af;">Bytes</span>.toBytes(<span style="color: #a31515;">"details"</span>), <span style="color: #2b91af;">Bytes</span>.toBytes(<span style="color: #a31515;">"total"</span>)));
            results.Add(<span style="color: blue;">new</span> <span style="color: #2b91af;">KeyValuePair</span>&lt;<span style="color: blue;">string</span>, <span style="color: blue;">int</span>&gt;(page, count));
        }
        <span style="color: blue;">return</span> results;
    }
}</pre>
<p>The above code defines a delegate that takes type AccessRecord as an argument and returns an IEnumerable wrapping a KeyValuePair type consisting of a string and an integer.</p>
<h4>Using the <em>Where</em> and <em>SelectMany</em> query operators</h4>
<p>The Java MapReduce job uses a table scan, in fact it&#8217;s the same scan used to implement the innermost-where LINQ provider. That means the MapReduce is really providing the same functionality, albeit much more efficiently, as the <em>OrderBy</em> and <em>GroupBy</em> query operators. Therefore, a LINQ query using the frequency delegate defined above does not require the two operators. In fact, the <em>Where</em> operator is not really needed. However, it would be nice to use the <em>Where</em> query operator as a means to define the predicate used by the table scan, even though the scan is running wholly on the Java side.</p>
<p>To support this, the method <em>HBaseQueryContext.Execute()</em> needs to be modified to determine if the <em>SelectMany</em> query operator will invoke the frequency delegate. If there&#8217;s no <em>SelectMany</em> operator in the expression tree, or, if there is, but it&#8217;s not invoking the frequency delegate, then the call to <em>HBaseHelper.GetColumnsFromHBase()</em> is made as before.</p>
<p>However, if the <em>SelectMany</em> operator is present and it&#8217;s invoking the frequency delegate, then a single AccessRecord instance is used to hold the arguments for the MapReduce.</p>
<pre style="font-family: Arial; font-size: 12px; color: black; background-color: white; padding-left: 30px;"><span style="color: #2b91af;">ColumnFinder</span> cf = <span style="color: blue;">new</span> <span style="color: #2b91af;">ColumnFinder</span>(lambdaExpression.Body);
<span style="color: #2b91af;">List</span>&lt;<span style="color: blue;">string</span>&gt; columns = cf.Columns;

<span style="color: #2b91af;">AccessRecord</span>[] records;
<span style="color: blue;">if</span> (expression.ToString().Contains(<span style="color: #a31515;">"SelectMany"</span>) 
            &amp;&amp; expression.ToString().Contains(<span style="color: #a31515;">"HBase.frequency"</span>))
{
    <span style="color: #2b91af;">List</span>&lt;<span style="color: #2b91af;">AccessRecord</span>&gt; aList = <span style="color: blue;">new</span> <span style="color: #2b91af;">List</span>&lt;<span style="color: #2b91af;">AccessRecord</span>&gt;();
    aList.Add(<span style="color: blue;">new</span> <span style="color: #2b91af;">AccessRecord</span>(columns.First&lt;<span style="color: blue;">string</span>&gt;(), (cf.IsIP ? <span style="color: #a31515;">"ip"</span> : <span style="color: #a31515;">"page"</span>)));
    records = aList.ToArray&lt;<span style="color: #2b91af;">AccessRecord</span>&gt;();
}
<span style="color: blue;">else</span>
{
    <span style="color: green;">// Call HBase and get the results.</span>
    records = <span style="color: #2b91af;">HBaseHelper</span>.GetColumnsFromHBase(columns.First&lt;<span style="color: blue;">string</span>&gt;(), cf.IsIP, cf.IsPage);
}</pre>
<h3>Testing the modified LINQ provider</h3>
<p>The test code has two LINQ queries. The first uses the innermost-where strategy, the second uses the SelectMany to invoke the frequency delegate that results in calling the Java MapReduce implementation. The code also provides some bench-marking times on the two queries.</p>
<pre style="font-family: Arial; font-size: 12px; color: black; background-color: white; padding-left: 30px;"><span style="color: blue;">static</span> <span style="color: blue;">void</span> Main(<span style="color: blue;">string</span>[] args)
{
    <span style="color: #2b91af;">DateTime</span> startTime;
    <span style="color: #2b91af;">DateTime</span> endTime;
    <span style="color: #2b91af;">TimeSpan</span> ts;

    <span style="color: #2b91af;">QueryableHBaseData</span>&lt;<span style="color: #2b91af;">AccessRecord</span>&gt; records =
        <span style="color: blue;">new</span> <span style="color: #2b91af;">QueryableHBaseData</span>&lt;<span style="color: #2b91af;">AccessRecord</span>&gt;();

    <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"Scan only"</span>);
    startTime = <span style="color: #2b91af;">DateTime</span>.Now;
    <span style="color: blue;">var</span> query1 = <span style="color: blue;">from</span> record <span style="color: blue;">in</span> records
                    <span style="color: blue;">where</span> record.ipAddress == <span style="color: #a31515;">"88.240.129.183"</span>
                    <span style="color: blue;">orderby</span> record.page
                    <span style="color: blue;">group</span> record <span style="color: blue;">by</span> record.page <span style="color: blue;">into</span> grps
                    <span style="color: blue;">select</span> <span style="color: blue;">new</span> { ip = grps.Key, count = grps.Count() };

    <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"  IP address 88.240.129.183 visted these pages"</span>);
    <span style="color: blue;">foreach</span> (<span style="color: blue;">var</span> pg <span style="color: blue;">in</span> query1)
    {
        <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"     page: "</span> + pg.ip + <span style="color: #a31515;">" "</span> + pg.count);
    }
    endTime = <span style="color: #2b91af;">DateTime</span>.Now;
    ts = endTime - startTime;
    <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"Elapsed time: "</span> + ts.TotalMilliseconds);

    <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"Scan and map/reduce"</span>);
    startTime = <span style="color: #2b91af;">DateTime</span>.Now;
    <span style="color: blue;">var</span> query2 = <span style="color: blue;">from</span> record <span style="color: blue;">in</span> records
                    <span style="color: blue;">where</span> record.ipAddress == <span style="color: #a31515;">"88.240.129.183"</span>
                    <span style="color: blue;">from</span> count <span style="color: blue;">in</span> <span style="color: #2b91af;">HBase</span>.frequency(record)
                    <span style="color: blue;">select</span> count;

    <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"  IP address 88.240.129.183 visted these pages"</span>);
    <span style="color: blue;">foreach</span> (<span style="color: #2b91af;">KeyValuePair</span>&lt;<span style="color: blue;">string</span>, <span style="color: blue;">int</span>&gt; kvp <span style="color: blue;">in</span> query2)
    {
        <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"     page: "</span> + kvp.Key + <span style="color: #a31515;">" "</span> + kvp.Value);
    }
    endTime = <span style="color: #2b91af;">DateTime</span>.Now;
    ts = endTime - startTime;
    <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"Elapsed time: "</span> + ts.TotalMilliseconds);
 }</pre>
<p>Here&#8217;s the output to the console. It&#8217;s obvious that the MapReduce LINQ provider runs in less than half the time of the innermost-where LINQ provider. That&#8217;s because the <em>OrderBy</em> and <em>GroupBy</em> query operators are required to process 8,474 AccessRecord objects.</p>
<pre style="font-family: Arial; font-size: 12px; color: black; background-color: white; padding-left: 30px;"><a href="http://www.jnbridge.com/jn/blog/2012/10/10/building-a-linq-provider-for-hbase-mapreduce/finaltest/" rel="attachment wp-att-1402"><img class="alignnone  wp-image-1402" src="http://www.jnbridge.com/jn/wp-content/blogs.dir/1/files/2012/10/finaltest.jpg" alt="" width="609" height="373" /></a></pre>
<h3>Conclusion</h3>
<p>Building a LINQ provider for HBase is relatively straight forward if a table scan using the HBase client API is mapped directly to a LINQ innermost <em>Where</em> query operator. However, the Where operation can result in a very large collection of objects residing in memory, therefore subsequent query operators like <em>OrderBy</em> and <em>GroupBy</em> are inefficient. Using HBase MapReduce to provide the equivalent functionality of the Where, OrderBy and GroupBy query operators in a single distributed, parallel computation is much faster, but it&#8217;s difficult to parse an expression tree of arbitrary query operators to determine if the query can be optimized to a set of MapReduce jobs.  The simple solution is to add a MapReduce operator called <em>frequency</em>.</p>
<h4>Acknowledgements and resources</h4>
<p>Thanks to Steve Willsens and MSDN for the LINQ  example, <em><a title="linqexample" href="http://code.msdn.microsoft.com/vstudio/LINQ-to-TerraServer-d6f7873b">LINQ to TerraServer Provider Sample</a>, </em>which supplied the classes that implement a LINQ expression parser. For an excellent discussion of the LINQ extensions to IEnumerable&lt;T&gt;, visit Raj Kaimal&#8217;s <em><a title="linqtoobjects" href="http://weblogs.asp.net/rajbk/archive/2010/03/29/how-linq-to-object-statements-work.aspx">How LINQ to Object statements work</a></em>. For a look at a HBase MapReduce implementation, visit Sujee Maniyam&#8217;s <em><a title="mapredex" href="http://sujee.net/tech/articles/hadoop/hbase-map-reduce-freq-counter/">Hbase Map Reduce Example-Frequency Counter</a>. </em></p>
<p>The source for this example can be downloaded <a href="http://www.jnbridge.com/labs/LinqToHBase.zip">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jnbridge.com/jn/blog/2012/10/10/building-a-linq-provider-for-hbase-mapreduce/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Problems with the Windows 8 Start Screen</title>
		<link>http://www.jnbridge.com/jn/blog/2012/10/03/the-problems-with-the-windows-8-start-screen/</link>
		<comments>http://www.jnbridge.com/jn/blog/2012/10/03/the-problems-with-the-windows-8-start-screen/#comments</comments>
		<pubDate>Wed, 03 Oct 2012 09:00:19 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Windows 8]]></category>

		<guid isPermaLink="false">http://www.jnbridge.com/jn/?p=1267</guid>
		<description><![CDATA[A lot of attention has been paid to the problems that enterprise users have with the new Windows 8 Start Screen. Most of the discussion seems to center around the fact that the old-style Start Menu is no longer available, but I don’t think that’s the issue. The problems are inherent in the new Start [...]]]></description>
				<content:encoded><![CDATA[<p>A lot of attention has been paid to the problems that enterprise users have with the new Windows 8 Start Screen. Most of the discussion seems to center around the fact that the old-style Start Menu is no longer available, but I don’t think that’s the issue. The problems are inherent in the new Start Screen itself, and the reason that the discussion is focused on the old Start Menu is simply that it happens to do the job better than the new Start Screen. I think that if Windows 8 had a navigation mechanism that helped enterprise users accomplish their tasks, nobody would be clamoring for the restoration of the old menu.</p>
<p>Here are what I think are the main problems with the Start Screen:</p>
<ul>
<li><em>It’s a poor use of screen real estate.</em> The main reason to use the Windows 8 desktop (aside from the fact that an application will only run on the desktop) is to have multiple applications and files open on the screen. Clicking on the Start button and having entire display taken up by the Start Screen is disruptive and breaks the desktop metaphor. The old Start Menu, on the other hand, only took up a small portion of the screen and could be quickly dismissed, restoring the screen to its previous state.
<p>Even worse, when multiple displays are used, Windows 8 allocates an entire display to the Start Screen. The old Start Menu never permanently monopolized a display.</li>
<li><em>It’s insufficiently hierarchical.</em> The new “Metro” (for want of a better term) apps are simple and self-contained, and the Start Screen is designed to display them in a uniform wall. Enterprise software is different and much more complex. Many enterprise products (including JNBridgePro and the JNBridge adapters) are suites of applications and associated tools and scripts, plus documentation, source code, and examples. When installed in Windows 8, everything is installed in a tile at the top level of the Start Screen. While it’s true that tiles can be grouped, that’s insufficient – we need ways to hide less-used tools, and to group applications and documents by function. The hierarchical folders of the old Start Menu serve that purpose just fine. The grouped tiles of the new Start Screen do not.</li>
<li><em>It’s unsuited for exploration.</em> Microsoft has stated that the main reason the Start Menu was phased out was that users typically pinned the applications they most frequently used to the task bar, and didn’t much use the Start Menu.  That’s probably true, but it doesn’t help much with complex enterprise applications that, as stated above, have multiple tools and documents, many of which aren’t frequently used and probably wouldn’t be pinned to the task bar. In addition, the user will likely not be aware of most of these more obscure tools and documents until they’re actually needed. In such cases, Microsoft suggests using the search mechanism to find the file by typing its name, but that assumes that (1) you know its name sufficiently accurately to get a good match in the search, and (2) you know that the file actually exists even before you search for it. Shouldn’t there be a usable mechanism for drilling down into the product’s installation hierarchy to discover these lesser-known tools and files? The old Start Menu allowed us to do this, but the new Start Screen doesn’t really support this activity very well.</li>
</ul>
<p>What do you think about the Windows 8 Start Screen? Do you think it will help you do your work, or will it get in the way. Leave a comment, or contact us at <a href="mailto:info@jnbridge.com">info@jnbridge.com</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jnbridge.com/jn/blog/2012/10/03/the-problems-with-the-windows-8-start-screen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
