blob: ab519ac04a8495c3242e8e0b5bfa24dfbcbfd0e9 [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="keywords" content="SMILA/Specifications/RecordStorage,Daniel.stucky.empolis.com,Tmenzel.brox.de" />
<link rel="shortcut icon" href="http://wiki.eclipse.org/SMILA/Specifications/favicon.ico" />
<link rel="search" type="application/opensearchdescription+xml" href="http://wiki.eclipse.org/opensearch_desc.php" title="Eclipsepedia (English)" />
<link rel="alternate" type="application/rss+xml" title="Eclipsepedia RSS Feed" href="http://wiki.eclipse.org/index.php?title=Special:Recentchanges&amp;feed=rss" />
<link rel="alternate" type="application/atom+xml" title="Eclipsepedia Atom Feed" href="http://wiki.eclipse.org/index.php?title=Special:Recentchanges&amp;feed=atom" />
<title>SMILA/Specifications/RecordStorage - Eclipsepedia</title>
<style type="text/css" media="screen,projection">/*<![CDATA[*/ @import "/skins/eclipsenova/novaWide.css?116"; /*]]>*/</style>
<link rel="stylesheet" type="text/css" media="print" href="http://wiki.eclipse.org/skins/eclipsenova/eclipsenovaPrint.css?116" />
<link rel="stylesheet" type="text/css" media="handheld" href="http://wiki.eclipse.org/skins/eclipsenova/handheld.css?116" />
<link rel="stylesheet" type="text/css" href="http://wiki.eclipse.org/skins/eclipsenova/Nova/css/header.css" media="screen" />
<link rel="stylesheet" type="text/css" href="http://wiki.eclipse.org/skins/eclipsenova/tabs.css" media="screen" />
<link rel="stylesheet" type="text/css" href="http://wiki.eclipse.org/skins/eclipsenova/Nova/css/visual.css" media="screen" />
<link rel="stylesheet" type="text/css" href="http://wiki.eclipse.org/skins/eclipsenova/Nova/css/layout.css" media="screen" />
<link rel="stylesheet" type="text/css" href="http://wiki.eclipse.org/skins/eclipsenova/Nova/css/footer.css" media="screen" />
<!--[if IE]><link rel="stylesheet" type="text/css" href="/skins/eclipsenova/IEpngfix.css" media="screen" /><![endif]-->
<!--[if lt IE 5.5000]><style type="text/css">@import "/skins/eclipsenova/IE50Fixes.css?116";</style> <![endif]-->
<!--[if IE 5.5000]><style type="text/css">@import "/skins/eclipsenova/IE55Fixes.css?116";</style><![endif]-->
<!--[if IE 6]><style type="text/css">@import "/skins/eclipsenova/IE60Fixes.css?116";</style><![endif]-->
<!--[if IE 7]><style type="text/css">@import "/skins/eclipsenova/IE70Fixes.css?116";</style><![endif]-->
<!--[if lt IE 7]><script type="text/javascript" src="/skins/common/IEFixes.js?116"></script>
<meta http-equiv="imagetoolbar" content="no" /><![endif]-->
<script type= "text/javascript">/*<![CDATA[*/
var skin = "eclipsenova";
var stylepath = "/skins";
var wgArticlePath = "/$1";
var wgScriptPath = "";
var wgScript = "/index.php";
var wgServer = "http://wiki.eclipse.org";
var wgCanonicalNamespace = "";
var wgCanonicalSpecialPageName = false;
var wgNamespaceNumber = 0;
var wgPageName = "SMILA/Specifications/RecordStorage";
var wgTitle = "SMILA/Specifications/RecordStorage";
var wgAction = "view";
var wgRestrictionEdit = [];
var wgRestrictionMove = [];
var wgArticleId = "17885";
var wgIsArticle = true;
var wgUserName = null;
var wgUserGroups = null;
var wgUserLanguage = "en";
var wgContentLanguage = "en";
var wgBreakFrames = false;
var wgCurRevisionId = "200356";
var wgVersion = "1.12.0";
var wgEnableAPI = true;
var wgEnableWriteAPI = false;
/*]]>*/</script>
<script type="text/javascript" src="http://wiki.eclipse.org/skins/common/wikibits.js?116"><!-- wikibits js --></script>
<!-- Performance mods similar to those for bug 166401 -->
<script type="text/javascript" src="http://wiki.eclipse.org/index.php?title=-&amp;action=raw&amp;gen=js&amp;useskin=eclipsenova"><!-- site js --></script>
<!-- Head Scripts -->
<script type="text/javascript" src="http://wiki.eclipse.org/skins/common/ajax.js?116"></script>
<style type="text/css">/*<![CDATA[*/
.source-java {line-height: normal; font-size: medium;}
.source-java li {line-height: normal;}
/**
* GeSHi Dynamically Generated Stylesheet
* --------------------------------------
* Dynamically generated stylesheet for java
* CSS class: source-java, CSS id:
* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter)
*/
.source-java .de1, .source-java .de2 {font-family: 'Courier New', Courier, monospace; font-weight: normal;}
.source-java {}
.source-java .head {}
.source-java .foot {}
.source-java .imp {font-weight: bold; color: red;}
.source-java .ln-xtra {color: #cc0; background-color: #ffc;}
.source-java li {font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;}
.source-java li.li2 {font-weight: bold;}
.source-java .kw1 {color: #7F0055; font-weight: bold;}
.source-java .kw2 {color: #7F0055; font-weight: bold;}
.source-java .kw3 {color: #000000; font-weight: normal}
.source-java .kw4 {color: #7F0055; font-weight: bold;}
.source-java .co1 {color: #3F7F5F; font-style: italic;}
.source-java .co2 {color: #3F7F5F;}
.source-java .co3 {color: #3F7F5F; font-style: italic; font-weight: bold;}
.source-java .coMULTI {color: #3F5FBF; font-style: italic;}
.source-java .es0 {color: #000000;}
.source-java .br0 {color: #000000;}
.source-java .st0 {color: #2A00ff;}
.source-java .nu0 {color: #000000;}
.source-java .me1 {color: #000000;}
.source-java .me2 {color: #000000;}
/*]]>*/
</style>
<style type="text/css">/*<![CDATA[*/
@import "/index.php?title=MediaWiki:Geshi.css&usemsgcache=yes&action=raw&ctype=text/css&smaxage=18000";
/*]]>*/
</style><style type="text/css">/*<![CDATA[*/
.source-xml {line-height: normal; font-size: medium;}
.source-xml li {line-height: normal;}
/**
* GeSHi Dynamically Generated Stylesheet
* --------------------------------------
* Dynamically generated stylesheet for xml
* CSS class: source-xml, CSS id:
* GeSHi (C) 2004 - 2007 Nigel McNie (http://qbnz.com/highlighter)
*/
.source-xml .de1, .source-xml .de2 {font-family: 'Courier New', Courier, monospace; font-weight: normal;}
.source-xml {}
.source-xml .head {}
.source-xml .foot {}
.source-xml .imp {font-weight: bold; color: red;}
.source-xml .ln-xtra {color: #cc0; background-color: #ffc;}
.source-xml li {font-family: 'Courier New', Courier, monospace; color: black; font-weight: normal; font-style: normal;}
.source-xml li.li2 {font-weight: bold;}
.source-xml .coMULTI {color: #808080; font-style: italic;}
.source-xml .es0 {color: #000099; font-weight: bold;}
.source-xml .br0 {color: #66cc66;}
.source-xml .st0 {color: #ff0000;}
.source-xml .nu0 {color: #cc66cc;}
.source-xml .sc0 {color: #00bbdd;}
.source-xml .sc1 {color: #ddbb00;}
.source-xml .sc2 {color: #339933;}
.source-xml .sc3 {color: #009900;}
.source-xml .re0 {color: #000066;}
.source-xml .re1 {font-weight: bold; color: black;}
.source-xml .re2 {font-weight: bold; color: black;}
/*]]>*/
</style>
<style type="text/css">/*<![CDATA[*/
@import "/index.php?title=MediaWiki:Geshi.css&usemsgcache=yes&action=raw&ctype=text/css&smaxage=18000";
/*]]>*/
</style><link rel="stylesheet" type="text/css" href="RecordStorage.html" /> </head>
<body class="mediawiki ns-0 ltr page-SMILA_Specifications_RecordStorage">
<div id="globalWrapper">
<div id="column-one">
<!-- Eclipse Additions for the Top Nav start here M. Ward-->
<div id="header">
<div id="header-graphic">
<img src="http://wiki.eclipse.org/skins/eclipsenova/eclipse.png" alt="Eclipse Wiki">
</div>
<!-- Pulled 101409 Mward -->
<div class="portlet" id="p-personal">
<div class="pBody">
<ul>
<li id="pt-login"><a href="http://wiki.eclipse.org/index.php?title=Special:Userlogin&amp;returnto=SMILA/Specifications/RecordStorage">Log in</a></li>
</ul>
</div>
</div>
<div id="header-icons">
<div id="sites">
<ul id="sitesUL">
<li><a href="http://www.eclipse.org"><img src="http://dev.eclipse.org/custom_icons/eclipseIcon.png" width="28" height="28" alt="Eclipse Foundation" title="Eclipse Foundation" /><div>Eclipse Foundation</div></a></li>
<li><a href="http://marketplace.eclipse.org"><img src="http://dev.eclipse.org/custom_icons/marketplace.png" width="28" height="28" alt="Eclipse Marketplace" title="Eclipse Marketplace" /><div>Eclipse Marketplace</div></a></li>
<li><a href="https://bugs.eclipse.org/bugs"><img src="http://dev.eclipse.org/custom_icons/system-search-bw.png" width="28" height="28" alt="Bugzilla" title="Bugzilla" /><div>Bugzilla</div></a></li>
<li><a href="http://live.eclipse.org"><img src="http://dev.eclipse.org/custom_icons/audio-input-microphone-bw.png" width="28" height="28" alt="Live" title="Live" /><div>Eclipse Live</div></a></li>
<li><a href="http://planeteclipse.org"><img src="http://dev.eclipse.org/large_icons/devices/audio-card.png" width="28" height="28" alt="PlanetEclipse" title="Planet" /><div>Planet Eclipse</div></a></li>
<li><a href="http://portal.eclipse.org"><img src="http://dev.eclipse.org/custom_icons/preferences-system-network-proxy-bw.png" width="28" height="28" alt="Portal" title="Portal" /><div>My Foundation Portal</div></a></li>
</ul>
</div>
</div>
</div>
<!-- NEW HEADER STUFF HERE -->
<div id="header-menu">
<div id="header-nav">
<ul> <li><a class="first_one" href="http://wiki.eclipse.org/" target="_self">Home</a></li> <li><a href="http://www.eclipse.org/downloads/" target="_self">Downloads</a></li>
<li><a href="http://www.eclipse.org/users/" target="_self">Users</a></li>
<li><a href="http://www.eclipse.org/membership/" target="_self">Members</a></li>
<li><a href="http://wiki.eclipse.org/index.php/Development_Resources" target="_self">Committers</a></li>
<li><a href="http://www.eclipse.org/resources/" target="_self">Resources</a></li>
<li><a href="http://www.eclipse.org/projects/" target="_self">Projects</a></li>
<li><a href="http://www.eclipse.org/org/" target="_self">About Us</a></li>
</ul>
</div>
<div id="header-utils">
<!-- moved the search window here -->
<form action="http://wiki.eclipse.org/Special:Search" >
<input class="input" name="search" type="text" accesskey="f" value="" />
<input type='submit' onclick="this.submit();" name="go" id="searchGoButton" class="button" title="Go to a page with this exact name if one exists" value="Go" />&nbsp;
<input type='submit' onclick="this.submit();" name="fulltext" class="button" id="mw-searchButton" title="Search Eclipsepedia for this text" value="Search" />
</form>
</div>
</div>
<!-- Eclipse Additions for the Header stop here -->
<!-- Additions and mods for leftside nav Start here -->
<!--Started nav rip here-->
<!-- these are the nav controls main page, changes etc -->
<div id="novaContent" class="faux">
<div id="leftcol">
<ul id="leftnav">
<!-- these are the page controls, edit history etc -->
<li class="separator"><a class="separator">Navigation &#160;&#160;</li>
<li id="n-mainpage"><a href="http://wiki.eclipse.org/Main_Page">Main Page</a></li>
<li id="n-portal"><a href="http://wiki.eclipse.org/Eclipsepedia:Community_Portal">Community portal</a></li>
<li id="n-currentevents"><a href="http://wiki.eclipse.org/Eclipsepedia:Current_events">Current events</a></li>
<li id="n-recentchanges"><a href="http://wiki.eclipse.org/Special:Recentchanges">Recent changes</a></li>
<li id="n-randompage"><a href="http://wiki.eclipse.org/Special:Random">Random page</a></li>
<li id="n-help"><a href="http://wiki.eclipse.org/Help:Contents">Help</a></li>
<li class="separator"><a class="separator">Toolbox &#160;&#160;</a></li>
<li id="t-whatlinkshere"><a href="http://wiki.eclipse.org/Special:Whatlinkshere/SMILA/Specifications/RecordStorage">What links here</a></li>
<li id="t-recentchangeslinked"><a href="http://wiki.eclipse.org/Special:Recentchangeslinked/SMILA/Specifications/RecordStorage">Related changes</a></li>
<!-- This is the toolbox section -->
<li id="t-upload"><a href="http://wiki.eclipse.org/Special:Upload">Upload file</a></li>
<li id="t-specialpages"><a href="http://wiki.eclipse.org/Special:Specialpages">Special pages</a></li>
<li id="t-print"><a href="http://wiki.eclipse.org/index.php?title=SMILA/Specifications/RecordStorage&amp;printable=yes">Printable version</a></li> <li id="t-permalink"><a href="http://wiki.eclipse.org/index.php?title=SMILA/Specifications/RecordStorage&amp;oldid=200356">Permanent link</a></li> </ul>
</div>
<!-- Additions and mods for leftside nav End here -->
<div id="column-content">
<div id="content">
<a name="top" id="top"></a>
<div id="tabs">
<ul class="primary">
<li class="active"><a href="RecordStorage.html"><span class="tab">Page</span></a></li>
<li><a href="http://wiki.eclipse.org/index.php?title=Talk:SMILA/Specifications/RecordStorage&amp;action=edit"><span class="tab">Discussion</span></a></li>
<li><a href="http://wiki.eclipse.org/index.php?title=SMILA/Specifications/RecordStorage&amp;action=edit"><span class="tab">View source</span></a></li>
<li><a href="http://wiki.eclipse.org/index.php?title=SMILA/Specifications/RecordStorage&amp;action=history"><span class="tab">History</span></a></li>
<li><a href="http://wiki.eclipse.org/index.php?title=Special:Userlogin&amp;returnto=SMILA/Specifications/RecordStorage"><span class="tab">Edit</span></a></li>
</ul>
</div>
<script type="text/javascript"> if (window.isMSIE55) fixalpha(); </script>
<h1 class="firstHeading">SMILA/Specifications/RecordStorage</h1>
<div id="bodyContent">
<h3 id="siteSub">From Eclipsepedia</h3>
<div id="contentSub"><span class="subpages">&lt; <a href="../../SMILA.html" title="SMILA">SMILA</a> | <a href="../Specifications.1.html" title="SMILA/Specifications">Specifications</a></span></div>
<div id="jump-to-nav">Jump to: <a href="RecordStorage.html#column-one">navigation</a>, <a href="RecordStorage.html#searchInput">search</a></div> <!-- start content -->
<table id="toc" class="toc" summary="Contents"><tr><td><div id="toctitle"><h2>Contents</h2></div>
<ul>
<li class="toclevel-1"><a href="RecordStorage.html#Description"><span class="tocnumber">1</span> <span class="toctext">Description</span></a></li>
<li class="toclevel-1"><a href="RecordStorage.html#Discussion"><span class="tocnumber">2</span> <span class="toctext">Discussion</span></a>
<ul>
<li class="toclevel-2"><a href="RecordStorage.html#prefer_JDBC_implementation_of_XS_.28KISS_pattern.29"><span class="tocnumber">2.1</span> <span class="toctext">prefer JDBC implementation of XS (KISS pattern)</span></a></li>
<li class="toclevel-2"><a href="RecordStorage.html#JPA.2FEclipseLink_vs._Performance"><span class="tocnumber">2.2</span> <span class="toctext">JPA/EclipseLink vs. Performance</span></a></li>
<li class="toclevel-2"><a href="RecordStorage.html#Why_JPA.2FEclipseLink_.3F"><span class="tocnumber">2.3</span> <span class="toctext">Why JPA/EclipseLink&nbsp;?</span></a></li>
</ul>
</li>
<li class="toclevel-1"><a href="RecordStorage.html#RecordStorage_Interface"><span class="tocnumber">3</span> <span class="toctext">RecordStorage Interface</span></a></li>
<li class="toclevel-1"><a href="RecordStorage.html#RecordStorage_based_on_JDBC_database"><span class="tocnumber">4</span> <span class="toctext">RecordStorage based on JDBC database</span></a></li>
<li class="toclevel-1"><a href="RecordStorage.html#RecordStorage_based_on_relational_database_using_eclipseLink"><span class="tocnumber">5</span> <span class="toctext">RecordStorage based on relational database using eclipseLink</span></a>
<ul>
<li class="toclevel-2"><a href="RecordStorage.html#Overview_on_JPA"><span class="tocnumber">5.1</span> <span class="toctext">Overview on JPA</span></a></li>
<li class="toclevel-2"><a href="RecordStorage.html#PoC_eclipseLink_JPA_RecordStorage_using_Oracle_DB_and_Smila_data_model"><span class="tocnumber">5.2</span> <span class="toctext">PoC eclipseLink JPA RecordStorage using Oracle DB and Smila data model</span></a></li>
<li class="toclevel-2"><a href="RecordStorage.html#PoC_eclipseLink_JPA_RecordStorage_using_Oracle_DB_and_Dao_Objects_for_Smila_data_model"><span class="tocnumber">5.3</span> <span class="toctext">PoC eclipseLink JPA RecordStorage using Oracle DB and Dao Objects for Smila data model</span></a>
<ul>
<li class="toclevel-3"><a href="RecordStorage.html#Enhanced_Dao_classes_for_restricted_selections_of_attributes"><span class="tocnumber">5.3.1</span> <span class="toctext">Enhanced Dao classes for restricted selections of attributes</span></a></li>
</ul>
</li>
<li class="toclevel-2"><a href="RecordStorage.html#PoC_eclipseLink_JPA_RecordStorage_using_Derby_DB_and_Dao_Objects_for_Smila_Data_model"><span class="tocnumber">5.4</span> <span class="toctext">PoC eclipseLink JPA RecordStorage using Derby DB and Dao Objects for Smila Data model</span></a></li>
</ul>
</li>
<li class="toclevel-1"><a href="RecordStorage.html#Serialization_of_Records"><span class="tocnumber">6</span> <span class="toctext">Serialization of Records</span></a></li>
<li class="toclevel-1"><a href="RecordStorage.html#PoC_Blackboard_using_RecordStorage_instead_of_XMLStorage"><span class="tocnumber">7</span> <span class="toctext">PoC Blackboard using RecordStorage instead of XMLStorage</span></a></li>
<li class="toclevel-1"><a href="RecordStorage.html#Links"><span class="tocnumber">8</span> <span class="toctext">Links</span></a></li>
</ul>
</td></tr></table><script type="text/javascript"> if (window.showTocToggle) { var tocShowText = "show"; var tocHideText = "hide"; showTocToggle(); } </script>
<a name="Description"></a><h1> <span class="mw-headline">Description</span></h1>
<p>As Berkeley XML DB will not be available in eclipse in the near future, we need an open source alternative to store record metadata. There is no requirement to use an XML database only, any storage that allows us to persist record metadata will suffice.
</p>
<a name="Discussion"></a><h1> <span class="mw-headline">Discussion</span></h1>
<a name="prefer_JDBC_implementation_of_XS_.28KISS_pattern.29"></a><h3> <span class="mw-headline"> prefer JDBC implementation of XS (KISS pattern) </span></h3>
<dl><dd> <a href="http://wiki.eclipse.org/User:Tmenzel.brox.de" title="User:Tmenzel.brox.de"> TM</a>: As far as i know we only have a problem with Berkley DB XML (BDX) as long as it is a <i>required</i> and not just <i>workswith</i> dependency. My idea so far is to provide an implementation for XS (Xml Storage) that is based on a simple JDBC solution, like you have described urself on this page. By this we at least provide a working solution. When wanting to use SMILA for large scale application including full functionality in regard to XS then this is possible in the scope of Eccenca (CE) which then includes BDX. <br /> I think such a path is fully legitimate and doesnt create too much work for us now such as implementing an JPA/EclipseLink implementation for XS including far reaching changes to core objects.
<dl><dd> <a href="http://wiki.eclipse.org/User:Daniel.stucky.empolis.com" title="User:Daniel.stucky.empolis.com">Daniel Stucky</a>: Thanks for your feedback Tom. I will try to clarify some issues. The basic <tt>RecordStorage</tt> interface (with 4 methods) is all we need from the Blackboard point of view to access records. All access is done based on record Ids, no query support is needed. By introducing the RecordStorage interface instead of the currently used XMLStorage and XSSConnection interfaces we gain an abstraction layer that allows us to change the underlying implementation more easily. So you could use the already available XMLStorage implementation using Berkely DB inside a RecordStorageXmlImpl. Or we could create some JDBC or eclipseLink based implementations. I also propose to provide additional functionality for query support (be it XQJ, SQL or whatever) not in the RecordStorage interface but via separate interfaces, e.g. <tt>RecordStorageQuery</tt>. I guess that these interfaces will depend on the implementation technology used and will evolve over time, so limiting ourselves to just one interface seems a bad idea. Then the RecordStorageXmlImpl could also support XQJ queries via such a second interface, which in turn could be used by an XQJ crawler for mashup use-cases. The default implementation of a RecordStore would not need to implement any of those additional query interfaces.
<dl><dd> <a href="http://wiki.eclipse.org/User:Tmenzel.brox.de" title="User:Tmenzel.brox.de"> TM</a>: Ahhh. I kind of missed the point that u wanted to add the RS Interface as an own layer. I was thinking: rename XSS Interface... <br />I think adding such an interface wont hurt much and i kind of like the idea of freedom that it gives to us. <br />In regard to the optional available interfaces: How would u go about getting those as a client? Would u try to
<ol><li> request a RecordStoreQuery OSGi service that might not be there, depending on ur config?
</li><li> cast the obtained RS Service to the RSQ Interface and see if that fails?
</li></ol>
<dl><dd> <a href="http://wiki.eclipse.org/User:Daniel.stucky.empolis.com" title="User:Daniel.stucky.empolis.com">Daniel Stucky</a>: Did not think to deeply about this, but I would say definitely option 1). Thinking in Declarative Services a MashUpService would require a RecordStoreQuery service and it would no be able to be activated without one. Thus the whole mashup functionality would not be avilable at runtime. Of course one has to think about clean exception handling and so on, but that's my basic idea.
</dd></dl>
</dd></dl>
</dd></dl>
</dd></dl>
<a name="JPA.2FEclipseLink_vs._Performance"></a><h3> <span class="mw-headline"> JPA/EclipseLink vs. Performance </span></h3>
<dl><dd> <a href="http://wiki.eclipse.org/User:Tmenzel.brox.de" title="User:Tmenzel.brox.de"> TM</a>: Having worked with Hibernate, which is another ORM Tool, i dont believe that EL/JPA is the way to go. IMO EL it is likely to create too much overhead, both in programming effort and performance. <br /> From past experience with Hibernate i have learned that mass data handling is not the use case for ORM tools. They even say so in an Hibernate book, that one should look for other solutions, if mass data handling is the primary use case. The reason for this: by default ORM tools will create entity object graphs from the data stored in the DB and handle all reads/updates through these objects. This is VERY expensive. Of course it would be possible to do plain SQL under the hood in conjunction with DAOs, but that we could do also w/o the ORM tool anyway.
<dl><dd> <a href="http://wiki.eclipse.org/User:Daniel.stucky.empolis.com" title="User:Daniel.stucky.empolis.com">Daniel Stucky</a>: I did set up a realy simple test comparing the current XMLStorage and my RecordStorage implementation, using some different settings. The test is a standard import of a filesystem source with 2500 xml files. The BerkeleyDB and the DerbyDB ran in process, wheras the Oracle DB ran on a remote server.
</dd></dl>
</dd></dl>
<dl><dd><dl><dd><table class="wikitable" style="text-align:left" border="1">
<tr>
<th> Storage </th><th> runtime
</th></tr>
<tr>
<td> XMLStorage with BerkeleyDB
</td><td> ~ 8:00 min
</td></tr>
<tr>
<td> RecordStorage with Derby (no query attributes)
</td><td> ~ 6:30 min
</td></tr>
<tr>
<td> RecordStorage with Derby (with query attributes)
</td><td> ~ 7:00 min
</td></tr>
<tr>
<td> RecordStorage with Oracle (no query attributes)
</td><td> ~ 5:00 min
</td></tr>
<tr>
<td> RecordStorage with Oracle (with query attributes)
</td><td> ~ 5:15 min
</td></tr></table></dd></dl></dd></dl>
<p><br />
</p>
<a name="Why_JPA.2FEclipseLink_.3F"></a><h3> <span class="mw-headline"> Why JPA/EclipseLink&nbsp;? </span></h3>
<dl><dd> <a href="http://wiki.eclipse.org/User:Tmenzel.brox.de" title="User:Tmenzel.brox.de"> TM</a>: With my remarks about performance: Can u point out where u see the advantages of using EL/JPA in SMILA?
<dl><dd> <a href="http://wiki.eclipse.org/User:Daniel.stucky.empolis.com" title="User:Daniel.stucky.empolis.com">Daniel Stucky</a>: Ok, some reasons to chosse eclipseLink/JPA.
<ul><li> in the long term we need to support relational databses as storage backends
</li><li> JPA is an open standard
</li><li> eclipseLink is an eclipse project, no license and CQ issues (Hybernate is no option because of license)
</li><li> database independent, easy switching by configuration
</li><li> also interesting technology for persisting delta indexing data
</li><li> we already use eclipseLink/PJA in ODE
</li></ul>
<dl><dd> <a href="http://wiki.eclipse.org/User:Tmenzel.brox.de" title="User:Tmenzel.brox.de">TM</a>:
<dl><dd> <tt> &gt; in the long term we need to support relational DBs as storage backends</tt>
</dd></dl>
</dd><dd> For Record/XML Storage? I wasnt aware of that! In what scenario? Why wont BDX do it? <br />So far I saw rel. DBs as 2nd best solutions where we put only little effort into.
</dd></dl>
</dd></dl>
</dd></dl>
<a name="RecordStorage_Interface"></a><h1> <span class="mw-headline">RecordStorage Interface</span></h1>
<p>Here is a proposal for a RecordStorage interface. It contains only the basic functionality without any query support.
</p>
<div dir="ltr" style="text-align: left;"><pre class="source-java"><span class="kw1">interface</span> RecordStorage
<span class="br0">&#123;</span>
Record loadRecord<span class="br0">&#40;</span>Id id<span class="br0">&#41;</span>;
<span class="kw4">void</span> storedRecord<span class="br0">&#40;</span>Record record<span class="br0">&#41;</span>;
<span class="kw4">void</span> removeRecord<span class="br0">&#40;</span>Id id<span class="br0">&#41;</span>;
<span class="kw4">boolean</span> existsRecord<span class="br0">&#40;</span>Id id<span class="br0">&#41;</span>
<span class="br0">&#125;</span></pre></div>
<p><br />
</p>
<a name="RecordStorage_based_on_JDBC_database"></a><h1> <span class="mw-headline">RecordStorage based on JDBC database</span></h1>
<p>At the moment all access to records is based on the record ID. The record ID is the primary key when reading/writing records. It would be easily possible to store the records in a relational database, using just one table with columns for the record ID (the primary key) and a second one to store the record itself. The record could be stored as a BLOB or CLOB:
</p>
<ul><li> BLOB: the record is just serialize into a byte[] and stored as a BLOB
</li><li> CLOB: the record's XML representation could be stored in a CLOB. Extra method calls to parse/convert the record from/to XML needs to be applied when reading/writing the records (performance impact in comparison to using a BLOB). But this would offer some options to include WHERE clauses accessing the CLOB in SQL queries
</li></ul>
<p>Because the String representation of IDs can be really long, an alternative could be to store a hash of the String. (This hash has to be computed whenever accessing the database)
In addition one could also add another column to store the source attribute of the record ID. This would allow easy access on all records of a data source to handle the use-case "reindexing without crawling"
</p><p>For advanced use-cases (e.g. Mash up) query support is needed (compare XQJ), e.g. to select all records of a certain mime type. It would be possible to add more columns or join tables for selected record attributes. Another option is to do post processing of selected records, filtering those records that do not match the query filter. This is functional equal to a SQL select but of course performance is very slow.
</p><p>When implementing a JDBC RecordStorage one should take care to use database neutral SQL statements, or make the statements to use configurable. A good practice could be to implement the reading/writing in DAO objects, so that database specific implementations of the DAOs could be provided to make use of special features. Most databases offer improved support for BLOBs and CLOBs.
</p><p>A good choice for an open source database is Apache Derby. The Apache License 2.0 is compatible to EPL, the database has a low footprint (2MB) and can be used in process as well as in client/server network mode. It is also already committed to Orbit. For a productive environment it would be easily possible to switch to any other JDBC database, like Oracle.
</p>
<a name="RecordStorage_based_on_relational_database_using_eclipseLink"></a><h1> <span class="mw-headline"> RecordStorage based on relational database using eclipseLink</span></h1>
<p>EclipseLink offers various options to persists Java objects. Below we go into detail about using eclipseLink with JPA (Java Persistence Api):
</p>
<a name="Overview_on_JPA"></a><h2> <span class="mw-headline">Overview on JPA</span></h2>
<p>A mapping of Java classes to a relational database schema is created by using annotations in java code or providing an XML configuration. The classes to be persisted (called Entities) are in general represented by database tables, member variables as columns in those tables. There are some requirements to be met:
</p>
<ul><li> an entity class must provide a non argument constructor (either public or protected)
</li><li> entity classes must be top level classes, no enums or interfaces
</li></ul>
<p>There exists two kinds of access types, where only one kind is usable per entity:
</p>
<ul><li>field based: direct access on member variables
</li><li>property based: Java Bean like access via getter- and setter-methods
</li></ul>
<p>An Entity must have a unique Id, this can be either
</p>
<ul><li>a simple key (just one member variable) (@Id)
</li><li>a composite key using multiple member variables. This implies the usage of an additional primary key class that contains the same member variables (same name and type) as the entity class (@Id + @idClass)
</li><li> an embedded key (@EmbeddedId)
</li></ul>
<p>Entities can have relations to other entities or contain embedded classes. Embedded classes are not entities themselves (but must meet the same requirements) and do not have a unique Id. They "belong" to the entity object embedding them. Version 1.0 of the JPA specification demands only support of one level of embedded objects. If more levels are supported depends on the implementation. Collections are also not allowed as embedded classes.
</p><p>For more information see <a href="http://wiki.eclipse.org/images/9/9e/Ejb-3_0-fr-spec-persistence.pdf" class="internal" title="Ejb-3 0-fr-spec-persistence.pdf">ejb-3_0-fr-spec-persistence.pdf</a>.
</p><p><br />
</p>
<a name="PoC_eclipseLink_JPA_RecordStorage_using_Oracle_DB_and_Smila_data_model"></a><h2> <span class="mw-headline">PoC eclipseLink JPA RecordStorage using Oracle DB and Smila data model</span></h2>
<ul><li> a JPA RecordStorage is always based on a concrete implementation of entities to persist. So it is not possible to implement a generic RecordStorage for any Record implementation but only for a specific implementation, in this case our default implementation RecordImpl, IdImpl , ...
</li><li>the classes of the Smila data model cannot be used as is, but have to meet the requirements of JPA (e.g. no argument constructor)
</li><li>the default implementation uses interfaces of other entity classes as types for member variables. These have to be replaced by concrete implementation types, for example
</li></ul>
<div dir="ltr" style="text-align: left;"><pre class="source-java">@<span class="kw3">Entity</span>
<span class="kw1">public</span> <span class="kw1">class</span> RecordImpl <span class="kw1">implements</span> Record, <span class="kw3">Serializable</span> <span class="br0">&#123;</span>
@EmbeddedId
<span class="kw1">private</span> IdImpl _id;
...
<span class="br0">&#125;</span></pre></div>
<p>instead of
</p>
<div dir="ltr" style="text-align: left;"><pre class="source-java">@<span class="kw3">Entity</span>
<span class="kw1">public</span> <span class="kw1">class</span> RecordImpl <span class="kw1">implements</span> Record, <span class="kw3">Serializable</span> <span class="br0">&#123;</span>
@EmbeddedId
<span class="kw1">private</span> Id _id;
...
<span class="br0">&#125;</span></pre></div>
<ul><li>the Smila coding conventions implicate some issues: the names for tables/columns are automatically generated by JPA using class and member variable names. The leading _ used in Smila for member variables leads to invalid SQL statements (at least with Oracle). Therefore it is necessary to define the names for every tables, join tables and columns manually by using annotations or xml configuration
</li><li>the Smila objects (Records, Id, Attribute, Annotation) are all structured recursively and most make also use of Collections or Maps as members
<ul><li> eclipseLink supports N levels of embedded objects
</li><li> recursive embedding of objects is NOT supported
</li><li>Collections/Maps of embedded classes are not supported in JPA 1.0 (will be supported in JPA 2.0). eclipseLink offers a so called DescriptorCustomizer which could be used to implement such a support (not considered in die PoC, needs further analysis)
</li><li>so it is not possible modeling the Smila classes as embedded objects, which would have been the most natural approach as all data belongs to a single record object
</li></ul>
</li><li> as an alternative one could try to model the relations between the various data model classes. This means all classes have to be annotated as separate Entity objects and each needs to have an own unique Id. Besides the Record object, no other object has a single member that could be used as a primary key. This is a major problem as for example a object of type Attribute is only unique by creating a primary key over all member variables, which in addition are Lists. Class LiteralImpl has another problem, as the member _value is of type Object, which is represented as a Blob in the database. But Blobs cannot be used as part of a primary key
<ul><li> <a href="http://wiki.eclipse.org/User:Daniel.stucky.empolis.com" title="User:Daniel.stucky.empolis.com">Daniel Stucky</a>&nbsp;: we could check if automatically generated Ids are useful in this scenario. This means that all Smila Entity objects have to add a new member variable (e.g. <tt>int _persistentId</tt> ). Most likely this approach still fails because of the recursive structure
</li></ul>
</li></ul>
<p><br />
</p>
<a name="PoC_eclipseLink_JPA_RecordStorage_using_Oracle_DB_and_Dao_Objects_for_Smila_data_model"></a><h2> <span class="mw-headline">PoC eclipseLink JPA RecordStorage using Oracle DB and Dao Objects for Smila data model</span></h2>
<p>The basic idea is to use a simpler data model than the Smila data model for persistence with JPA, by storing des Smila data model as serialized data in this simplified data model. Thereby the restrictions concerning recursion and Collection/Map support should be solved.
</p><p>For the class RecordImpl a Dao class will be implemented, that serializes the Record object into a member variable:
</p>
<div dir="ltr" style="text-align: left;"><pre class="source-java">@<span class="kw3">Entity</span>
@Table<span class="br0">&#40;</span>name = <span class="st0">&quot;RECORDS&quot;</span><span class="br0">&#41;</span>
<span class="kw1">public</span> <span class="kw1">class</span> RecordDao <span class="kw1">implements</span> <span class="kw3">Serializable</span> <span class="br0">&#123;</span>
&nbsp;
@Id
@Column<span class="br0">&#40;</span>name = <span class="st0">&quot;ID&quot;</span><span class="br0">&#41;</span>
<span class="kw1">private</span> <span class="kw3">String</span> _idString;
&nbsp;
@Column<span class="br0">&#40;</span>name = <span class="st0">&quot;RECORD&quot;</span><span class="br0">&#41;</span>
<span class="kw1">private</span> <span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> _serializedRecord;
&nbsp;
<span class="kw1">protected</span> RecordDao<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw1">public</span> RecordDao<span class="br0">&#40;</span>Record record<span class="br0">&#41;</span> <span class="kw1">throws</span> <span class="kw3">IOException</span> <span class="br0">&#123;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>record == <span class="kw2">null</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
<span class="kw1">throw</span> <span class="kw1">new</span> <span class="kw3">IllegalArgumentException</span><span class="br0">&#40;</span><span class="st0">&quot;parameter record is null&quot;</span><span class="br0">&#41;</span>;
<span class="br0">&#125;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>record.<span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span> == <span class="kw2">null</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
<span class="kw1">throw</span> <span class="kw1">new</span> <span class="kw3">IllegalArgumentException</span><span class="br0">&#40;</span><span class="st0">&quot;parameter record has not Id set&quot;</span><span class="br0">&#41;</span>;
<span class="br0">&#125;</span>
&nbsp;
<span class="kw1">final</span> <span class="kw3">ByteArrayOutputStream</span> byteStream = <span class="kw1">new</span> <span class="kw3">ByteArrayOutputStream</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
<span class="kw1">final</span> <span class="kw3">ObjectOutputStream</span> objectStream = <span class="kw1">new</span> <span class="kw3">ObjectOutputStream</span><span class="br0">&#40;</span>byteStream<span class="br0">&#41;</span>;
objectStream.<span class="me1">writeObject</span><span class="br0">&#40;</span>record<span class="br0">&#41;</span>;
objectStream.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
_serializedRecord = byteStream.<span class="me1">toByteArray</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
_idString = record.<span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">toString</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
<span class="br0">&#125;</span>
&nbsp;
<span class="kw1">public</span> Record toRecord<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw1">throws</span> <span class="kw3">IOException</span>, <span class="kw3">ClassNotFoundException</span> <span class="br0">&#123;</span>
<span class="kw1">final</span> <span class="kw3">ObjectInputStream</span> objectStream = <span class="kw1">new</span> <span class="kw3">ObjectInputStream</span><span class="br0">&#40;</span><span class="kw1">new</span> <span class="kw3">ByteArrayInputStream</span><span class="br0">&#40;</span>_serializedRecord<span class="br0">&#41;</span><span class="br0">&#41;</span>;
<span class="kw1">final</span> Record record = <span class="br0">&#40;</span>Record<span class="br0">&#41;</span> objectStream.<span class="me1">readObject</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
objectStream.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
<span class="kw1">return</span> record;
<span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></div>
<p>In the database a table RECORDS will be created having the columns
</p>
<ul><li> ID - VARCHAR
</li><li> RECORD - BLOB
</li></ul>
<p>The ID is a String representation of the Id of the Record. It us used as a primary key in the database. It is not used during deserialisation of the Record. The Id object itself is automatically serialized with the Record object. The interface RecordStorage would be left unchanged. Internally the eclipseLink EntityManager works with RecordDao objects instead of RecordImpl objects.
</p>
<a name="Enhanced_Dao_classes_for_restricted_selections_of_attributes"></a><h3> <span class="mw-headline">Enhanced Dao classes for restricted selections of attributes</span></h3>
<p>For advanced uses cases there is a need to select records by queries. This could be realized by adding fixed and/or configurable Record attributes to the Dao class. These would be use to allow for filtering of selected attribute value pairs. They are not used to reconstruct the Record during deserialization. They are just data stored in addition to the serialized record.
</p><p>A fixed attribute could be the source element of the Record Id. It could be used to select records based on the data source (use-case build index without crawling). The RecordDao would be enhanced by the following member variable:
</p>
<div dir="ltr" style="text-align: left;"><pre class="source-java">@Column<span class="br0">&#40;</span>name = <span class="st0">&quot;SOURCE&quot;</span><span class="br0">&#41;</span>
<span class="kw1">private</span> <span class="kw3">String</span> _source;</pre></div>
<p>That would result in an additional column SOURCE in the table RECORDS.
</p><p>For configurable attributes the RecordDao would be enhanced with a list of Dao objects for attribute values called AttributeDao:
</p>
<div dir="ltr" style="text-align: left;"><pre class="source-java">@OneToMany<span class="br0">&#40;</span>targetEntity = AttributeDao.<span class="kw1">class</span>, cascade = CascadeType.<span class="me1">ALL</span><span class="br0">&#41;</span>
@JoinTable<span class="br0">&#40;</span>name = <span class="st0">&quot;RECORD_ATTRIBUTES&quot;</span>, joinColumns = @JoinColumn<span class="br0">&#40;</span>name = <span class="st0">&quot;RECORD_ID&quot;</span>, referencedColumnName = <span class="st0">&quot;ID&quot;</span><span class="br0">&#41;</span>,
inverseJoinColumns = @JoinColumn<span class="br0">&#40;</span>name = <span class="st0">&quot;ATTRIBUTE_ID&quot;</span>, referencedColumnName = <span class="st0">&quot;ATT_ID&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
List&lt;AttributeDao&gt; _attributes;</pre></div>
<p>The AttributeDao class could be implemented like this:
</p>
<div dir="ltr" style="text-align: left;"><pre class="source-java">@<span class="kw3">Entity</span>
@Table<span class="br0">&#40;</span>name = <span class="st0">&quot;ATTRIBUTES&quot;</span><span class="br0">&#41;</span>
<span class="kw1">public</span> <span class="kw1">class</span> AttributeDao <span class="br0">&#123;</span>
&nbsp;
@Id
@GeneratedValue<span class="br0">&#40;</span>strategy=GenerationType.<span class="me1">AUTO</span><span class="br0">&#41;</span>
@Column<span class="br0">&#40;</span>name = <span class="st0">&quot;ATT_ID&quot;</span><span class="br0">&#41;</span>
<span class="kw1">private</span> <span class="kw3">String</span> _id;
&nbsp;
@Column<span class="br0">&#40;</span>name = <span class="st0">&quot;ATT_NAME&quot;</span><span class="br0">&#41;</span>
<span class="kw1">private</span> <span class="kw3">String</span> _name;
&nbsp;
@BasicCollection <span class="br0">&#40;</span>
fetch=FetchType.<span class="me1">EAGER</span>,
valueColumn=@Column<span class="br0">&#40;</span>name=<span class="st0">&quot;ATT_VALUE&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
@CollectionTable <span class="br0">&#40;</span>
name=<span class="st0">&quot;ATTRIBUTE_VALUES&quot;</span>,
primaryKeyJoinColumns=
<span class="br0">&#123;</span>@PrimaryKeyJoinColumn<span class="br0">&#40;</span>name=<span class="st0">&quot;ATT_ID&quot;</span>, referencedColumnName=<span class="st0">&quot;ATT_ID&quot;</span><span class="br0">&#41;</span><span class="br0">&#125;</span>
<span class="br0">&#41;</span>
<span class="kw1">private</span> List&lt;String&gt; _values;
&nbsp;
<span class="kw1">protected</span> AttributeDao<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw1">public</span> AttributeDao<span class="br0">&#40;</span><span class="kw3">String</span> name<span class="br0">&#41;</span> <span class="br0">&#123;</span>
_name = name;
_values = <span class="kw1">new</span> ArrayList&lt;String&gt;<span class="br0">&#40;</span><span class="br0">&#41;</span>;
<span class="br0">&#125;</span>
&nbsp;
<span class="kw1">public</span> <span class="kw4">void</span> addValue<span class="br0">&#40;</span><span class="kw3">String</span> value<span class="br0">&#41;</span>
<span class="br0">&#123;</span>
_values.<span class="me1">add</span><span class="br0">&#40;</span>value<span class="br0">&#41;</span>;
<span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></div>
<p>Summing up all modifications the final database schema could look like this:
</p><p><a href="http://wiki.eclipse.org/Image:Db_schema.png" class="image" title="RecordStorage database schema"><img alt="RecordStorage database schema" src="http://wiki.eclipse.org/images/b/b7/Db_schema.png" width="555" height="409" border="0" /></a>
</p><p><br />
By a configuration the RecordStorage is told which Record attributes it should persists in the database in addition to the serialized Record. Neither Annotations nor Sub-Attributes are supported in this approach, just the Literals of the Attribute are stored. Of course more advanced enhancements are possible (but were not in the scope of this PoC)
</p><p><br />
The RecordStorage interface could add the following methods to support simple queries. Another option is to introduce another interface, e.g. RecordQueries to leave the basic Record functionality in a separate interface.
</p>
<div dir="ltr" style="text-align: left;"><pre class="source-java"><span class="kw1">interface</span> RecordStorage
<span class="br0">&#123;</span>
<span class="co1">// simple query functionality</span>
Iterator&lt;Record&gt; findRecordsBySource<span class="br0">&#40;</span><span class="kw3">String</span> source<span class="br0">&#41;</span>;
Iterator&lt;Record&gt; findRecordsByAttribute<span class="br0">&#40;</span><span class="kw3">String</span> name, <span class="kw3">String</span> value<span class="br0">&#41;</span>;
Iterator&lt;Record&gt; findRecordsByNativeQuery<span class="br0">&#40;</span><span class="kw3">String</span> whereClause<span class="br0">&#41;</span>;
<span class="br0">&#125;</span></pre></div>
<p>The first method can be realized by a JPQL NamedQuery. This is just an Annotation of the RecordDao class used by the RecordStorage implementation:
</p>
<div dir="ltr" style="text-align: left;"><pre class="source-java">@NamedQueries<span class="br0">&#40;</span><span class="br0">&#123;</span>
@NamedQuery<span class="br0">&#40;</span>name=<span class="st0">&quot;RecordDao.findBySource&quot;</span>,
query=<span class="st0">&quot;SELECT r FROM RecordDao r WHERE r._source =&nbsp;:source&quot;</span><span class="br0">&#41;</span>,
<span class="br0">&#125;</span><span class="br0">&#41;</span></pre></div>
<p>An implementation of the method could look like this:
</p>
<div dir="ltr" style="text-align: left;"><pre class="source-java"><span class="kw1">public</span> Iterator&lt;Record&gt; findRecordsBySource<span class="br0">&#40;</span><span class="kw1">final</span> <span class="kw3">String</span> source<span class="br0">&#41;</span> <span class="br0">&#123;</span>
Query query = _em.<span class="me1">createNamedQuery</span><span class="br0">&#40;</span><span class="st0">&quot;RecordDao.findBySource&quot;</span><span class="br0">&#41;</span>;
List&lt;RecordDao&gt; daos = query.<span class="me1">setParameter</span><span class="br0">&#40;</span><span class="st0">&quot;source&quot;</span>, source<span class="br0">&#41;</span>.<span class="me1">getResultList</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
<span class="kw1">return</span> <span class="kw1">new</span> RecordIterator<span class="br0">&#40;</span>daos.<span class="me1">iterator</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;
<span class="br0">&#125;</span></pre></div>
<p>The helper class <tt>RecordIterator</tt> is needed to convert the RecordDao objects into Records during iteration.
</p><p><br />
The second method is in JPA 1.0 not expressible as a JPQL NamedQuery Annotation, as it lacks the functionality to select values in a Collection. Therefore we have to use an eclipseLink enhancement and generate the query in java code:
</p>
<div dir="ltr" style="text-align: left;"><pre class="source-java"><span class="kw1">public</span> Iterator&lt;Record&gt; findRecordsByAttribute<span class="br0">&#40;</span><span class="kw1">final</span> <span class="kw3">String</span> name, <span class="kw1">final</span> <span class="kw3">String</span> value<span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp;
<span class="kw1">final</span> Session session = JpaHelper.<span class="me1">getServerSession</span><span class="br0">&#40;</span>_emf<span class="br0">&#41;</span>;
<span class="kw1">final</span> ReadAllQuery query = <span class="kw1">new</span> ReadAllQuery<span class="br0">&#40;</span>RecordDao.<span class="kw1">class</span><span class="br0">&#41;</span>;
&nbsp;
ExpressionBuilder record = <span class="kw1">new</span> ExpressionBuilder<span class="br0">&#40;</span><span class="br0">&#41;</span>;
Expression attributes = record.<span class="me1">anyOf</span><span class="br0">&#40;</span><span class="st0">&quot;_attributes&quot;</span><span class="br0">&#41;</span>;
Expression criteria = attributes.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&quot;_name&quot;</span><span class="br0">&#41;</span>.<span class="me1">equal</span><span class="br0">&#40;</span>name<span class="br0">&#41;</span>;
criteria = criteria.<span class="me1">and</span><span class="br0">&#40;</span>attributes.<span class="me1">anyOf</span><span class="br0">&#40;</span><span class="st0">&quot;_values&quot;</span><span class="br0">&#41;</span>.<span class="me1">equal</span><span class="br0">&#40;</span>value<span class="br0">&#41;</span><span class="br0">&#41;</span>;
query.<span class="me1">setSelectionCriteria</span><span class="br0">&#40;</span>criteria<span class="br0">&#41;</span>;
query.<span class="me1">dontUseDistinct</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
&nbsp;
List&lt;RecordDao&gt; daos = <span class="br0">&#40;</span>List&lt;RecordDao&gt;<span class="br0">&#41;</span>session.<span class="me1">executeQuery</span><span class="br0">&#40;</span>query<span class="br0">&#41;</span>;
<span class="kw1">return</span> <span class="kw1">new</span> RecordIterator<span class="br0">&#40;</span>daos.<span class="me1">iterator</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;
<span class="br0">&#125;</span></pre></div>
<ul><li> <a href="http://wiki.eclipse.org/User:Daniel.stucky.empolis.com" title="User:Daniel.stucky.empolis.com">Daniel Stucky</a>&nbsp;: At the moment there is a problem as the generated SQL query uses DISTINCT which is not allowed in conjunction with Blobs
<ul><li> <a href="http://wiki.eclipse.org/User:Daniel.stucky.empolis.com" title="User:Daniel.stucky.empolis.com">Daniel Stucky</a>&nbsp;: solved by using <tt>query.dontUseDistinct();</tt>
</li></ul>
</li></ul>
<p>The last method is a more generic variant that allows selection of Records via native SQL. As the results of the SQL query must be Record objects it is only allowed to enter the WHERE clause of the SQL statement which is combined with the static <tt>SELECT * FROM RECORDS </tt>
</p>
<div dir="ltr" style="text-align: left;"><pre class="source-java"><span class="kw1">public</span> Iterator&lt;Record&gt; findRecordsByNativeQuery<span class="br0">&#40;</span><span class="kw1">final</span> <span class="kw3">String</span> whereClause<span class="br0">&#41;</span> <span class="br0">&#123;</span>
<span class="kw3">String</span> sqlString = <span class="st0">&quot;SELECT * FROM RECORDS &quot;</span> + whereClause;
Query query = _em.<span class="me1">createNativeQuery</span><span class="br0">&#40;</span>sqlString, RecordDao.<span class="kw1">class</span><span class="br0">&#41;</span>;
List&lt;RecordDao&gt; daos = query.<span class="me1">getResultList</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
<span class="kw1">return</span> <span class="kw1">new</span> RecordIterator<span class="br0">&#40;</span>daos.<span class="me1">iterator</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;
<span class="br0">&#125;</span></pre></div>
<p>All these enhancements are just suggestions. Other solutions to support selection of records via queries are possible.
</p><p><br />
</p>
<a name="PoC_eclipseLink_JPA_RecordStorage_using_Derby_DB_and_Dao_Objects_for_Smila_Data_model"></a><h2> <span class="mw-headline">PoC eclipseLink JPA RecordStorage using Derby DB and Dao Objects for Smila Data model</span></h2>
<p>by using eclipseLink the concrete database used to persists the objects can easily be interchanged (provided that in the Entity mappings no database specific data types are used). Therefore it's quite easy to change the configuration from Oracle to Derby. In the file <tt>persistence.xml</tt> the following lines need to be changed:
</p>
<div dir="ltr" style="text-align: left;"><pre class="source-xml"><span class="sc3"><span class="re1">&lt;property</span> <span class="re0">name</span>=<span class="st0">&quot;eclipselink.jdbc.driver&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;org.apache.derby.jdbc.ClientDriver&quot;</span><span class="re2">/&gt;</span></span>
<span class="sc3"><span class="re1">&lt;property</span> <span class="re0">name</span>=<span class="st0">&quot;eclipselink.jdbc.url&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;jdbc:derby://localhost:1527/smiladb&quot;</span><span class="re2">/&gt;</span></span>
<span class="sc3"><span class="re1">&lt;property</span> <span class="re0">name</span>=<span class="st0">&quot;eclipselink.target-database&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;org.eclipse.persistence.platform.database.DerbyPlatform&quot;</span><span class="re2">/&gt;</span></span>
<span class="sc3"><span class="re1">&lt;property</span> <span class="re0">name</span>=<span class="st0">&quot;eclipselink.jdbc.password&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;app&quot;</span><span class="re2">/&gt;</span></span>
<span class="sc3"><span class="re1">&lt;property</span> <span class="re0">name</span>=<span class="st0">&quot;eclipselink.jdbc.user&quot;</span> <span class="re0">value</span>=<span class="st0">&quot;app&quot;</span><span class="re2">/&gt;</span></span></pre></div>
<p>It is required that the file <tt>persistence.xml</tt> is part of the classpath of the bundle. Therefore in an OSGi scenario it is not really handy to use this file to configure the database to use for persistence. Instead we could use the same approach as ODE: the database properties are stored in a separate property file which is located in the regular configuration folder of the RecordStorage implementation bundle. These properties are read during activation of the service and are passed to the EntityManager. All static settings for the Persistence-Unit remain in file <tt>persistence.xml</tt>.
</p><p><br />
</p>
<a name="Serialization_of_Records"></a><h1> <span class="mw-headline">Serialization of Records</span></h1>
<p>Java offers an easy way to serialize objects by implementing interface Serializable. Via an ObjectOutputStream arbitrary objects can be serialized in this way. This kind of serialization is used for example when using remote communication (e.g. RMI). Unfortunately we cannot use this default serialization for persisting the Record objects. We do not want to store the attachments of a Record with the Record, these are already stored by the BinaryStorage. But we want the attachments to be included in a remote communication. Therefore we cannot overwrite writeObject() of class RecordImpl.
Instead, the serialization is done in the RecordDao constructor. Here not the complete record is serialized but only selected parts. That means that not the attachments but only the attachment names are serialized persisted:
</p>
<div dir="ltr" style="text-align: left;"><pre class="source-java"><span class="kw1">public</span> RecordDao<span class="br0">&#40;</span>Record record<span class="br0">&#41;</span> <span class="kw1">throws</span> <span class="kw3">IOException</span> <span class="br0">&#123;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>record == <span class="kw2">null</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
<span class="kw1">throw</span> <span class="kw1">new</span> <span class="kw3">IllegalArgumentException</span><span class="br0">&#40;</span><span class="st0">&quot;parameter record is null&quot;</span><span class="br0">&#41;</span>;
<span class="br0">&#125;</span>
<span class="kw1">if</span> <span class="br0">&#40;</span>record.<span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span> == <span class="kw2">null</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
<span class="kw1">throw</span> <span class="kw1">new</span> <span class="kw3">IllegalArgumentException</span><span class="br0">&#40;</span><span class="st0">&quot;parameter record has not Id set&quot;</span><span class="br0">&#41;</span>;
<span class="br0">&#125;</span>
&nbsp;
List&lt;String&gt; attachmentNames = <span class="kw1">new</span> ArrayList&lt;String&gt;<span class="br0">&#40;</span><span class="br0">&#41;</span>;
<span class="kw1">for</span> <span class="br0">&#40;</span>Iterator&lt;String&gt; names = record.<span class="me1">getAttachmentNames</span><span class="br0">&#40;</span><span class="br0">&#41;</span>; names.<span class="me1">hasNext</span><span class="br0">&#40;</span><span class="br0">&#41;</span>; <span class="br0">&#41;</span> <span class="br0">&#123;</span>
attachmentNames.<span class="me1">add</span><span class="br0">&#40;</span>names.<span class="me1">next</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;
<span class="br0">&#125;</span>
&nbsp;
<span class="kw1">final</span> <span class="kw3">ByteArrayOutputStream</span> byteStream = <span class="kw1">new</span> <span class="kw3">ByteArrayOutputStream</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
<span class="kw1">final</span> <span class="kw3">ObjectOutputStream</span> objectStream = <span class="kw1">new</span> <span class="kw3">ObjectOutputStream</span><span class="br0">&#40;</span>byteStream<span class="br0">&#41;</span>;
&nbsp;
objectStream.<span class="me1">writeObject</span><span class="br0">&#40;</span>record.<span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;
objectStream.<span class="me1">writeObject</span><span class="br0">&#40;</span>record.<span class="me1">getMetadata</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;
objectStream.<span class="me1">writeObject</span><span class="br0">&#40;</span>attachmentNames<span class="br0">&#41;</span>;
objectStream.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
&nbsp;
_serializedRecord = byteStream.<span class="me1">toByteArray</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
_idString = record.<span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">toString</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
_source = record.<span class="me1">getId</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">getSource</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
<span class="br0">&#125;</span></pre></div>
<p><br />
In method <tt>toRecord()</tt> the serialized parts are desterilized and a new Record object is created:
</p>
<div dir="ltr" style="text-align: left;"><pre class="source-java"><span class="kw1">public</span> Record toRecord<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="kw1">throws</span> <span class="kw3">IOException</span>, <span class="kw3">ClassNotFoundException</span> <span class="br0">&#123;</span>
<span class="kw1">final</span> <span class="kw3">ObjectInputStream</span> objectStream = <span class="kw1">new</span> <span class="kw3">ObjectInputStream</span><span class="br0">&#40;</span><span class="kw1">new</span> <span class="kw3">ByteArrayInputStream</span><span class="br0">&#40;</span>_serializedRecord<span class="br0">&#41;</span><span class="br0">&#41;</span>;
&nbsp;
<span class="kw1">final</span> org.<span class="me1">eclipse</span>.<span class="me1">smila</span>.<span class="me1">datamodel</span>.<span class="me1">id</span>.<span class="me1">Id</span> id = <span class="br0">&#40;</span>org.<span class="me1">eclipse</span>.<span class="me1">smila</span>.<span class="me1">datamodel</span>.<span class="me1">id</span>.<span class="me1">Id</span><span class="br0">&#41;</span> objectStream.<span class="me1">readObject</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
<span class="kw1">final</span> MObject metadata = <span class="br0">&#40;</span>MObject<span class="br0">&#41;</span> objectStream.<span class="me1">readObject</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
<span class="kw1">final</span> List&lt;String&gt; attachmentNames = <span class="br0">&#40;</span>List&lt;String&gt;<span class="br0">&#41;</span> objectStream.<span class="me1">readObject</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
<span class="kw1">final</span> Record record = RecordFactory.<span class="me1">DEFAULT_INSTANCE</span>.<span class="me1">createRecord</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
record.<span class="me1">setId</span><span class="br0">&#40;</span>id<span class="br0">&#41;</span>;
record.<span class="me1">setMetadata</span><span class="br0">&#40;</span>metadata<span class="br0">&#41;</span>;
<span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw3">String</span> name&nbsp;: attachmentNames<span class="br0">&#41;</span> <span class="br0">&#123;</span>
record.<span class="me1">setAttachment</span><span class="br0">&#40;</span>name, <span class="kw2">null</span><span class="br0">&#41;</span>;
<span class="br0">&#125;</span>
&nbsp;
objectStream.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;
<span class="kw1">return</span> record;
<span class="br0">&#125;</span></pre></div>
<p>It also may make sense to implement a JDK independent serialization of these objects.
</p><p><br />
</p>
<a name="PoC_Blackboard_using_RecordStorage_instead_of_XMLStorage"></a><h1> <span class="mw-headline">PoC Blackboard using RecordStorage instead of XMLStorage</span></h1>
<p>It is not a big deal to replace the XMLStorage with a new RecordStorage and adopt the Blackboard accordingly. We have to adopt the manifest, some methods, the declarative service description and of course the launch configuration.
But there are some issues that need to be taken care of when implementing a RecordStorage:
</p>
<ul><li> class AnnotatableImpl has a member of type <tt> org.apache.commons.collections.map.MultiValueMap</tt> that is not serializable. Thus the complete Record is not serializable. We have to find a replacement implementation
</li><li> JPA transactions must be handled safely (use commit and rollback)
</li><li> write access on the EntityManager must be synchronized, either by
<ul><li> specifying the appropriate methods with <tt>synchronized</tt>. Not an ideal solution for our multi threaded architecture
</li><li> using a separate EntityManager per transaction. A global EntityManager instance could be used for all READ access and every WRITE transaction creates a new EntityManager (currently implemented)
</li><li> using an EntityManager per Thread (using ThreadLocal). As the RecordStorage will be implemented as an OSGi service, there is a problem during deactivation of the service. It has no access to the thread specific EntityManagers and can't close them and remove them from the ThreadLocal list. This may lead to memory leaks.
</li></ul>
</li><li> it may happen that some data (Ids, attribute names or values) will exceed the maximum size reserved in a database field. There exists no real solution for this problem, perhaps we should always use the possible maximum size
</li><li>when used in an OSGi environment the EntityManager needs to have access to the JDBC driver classes. This means that the RecordStorage bundle manifest needs to import these packages (e.g. <tt>org.apache.derby.jdbc</tt>). Functional this is not a problem, but this is a hard dependency on a JDBC driver and it is not possible anymore to use another driver by just configuring the database properties. The driver has to be included in the bundle's manifest first&nbsp;!
<ul><li> <a href="http://wiki.eclipse.org/User:Daniel.stucky.empolis.com" title="User:Daniel.stucky.empolis.com">Daniel Stucky</a>: I posted a question concerning this behavior to eclipseLink ( [<a href="http://dev.eclipse.org/mhonarc/lists/eclipselink-users/msg02010.html" class="external free" title="http://dev.eclipse.org/mhonarc/lists/eclipselink-users/msg02010.html" rel="nofollow">http://dev.eclipse.org/mhonarc/lists/eclipselink-users/msg02010.html</a>].). The issue may be solved in a future release.
</li></ul>
</li></ul>
<p><br />
</p>
<a name="Links"></a><h1> <span class="mw-headline">Links</span></h1>
<ul><li>[<a href="http://db.apache.org/derby/" class="external free" title="http://db.apache.org/derby/" rel="nofollow">http://db.apache.org/derby/</a>] (Derby homepage)
</li><li>[<a href="http://wiki.eclipse.org/EclipseLink/" class="external free" title="http://wiki.eclipse.org/EclipseLink/" rel="nofollow">http://wiki.eclipse.org/EclipseLink/</a>] (EclipseLink homepage)
</li><li>[<a href="http://jcp.org/en/jsr/detail?id=220" class="external free" title="http://jcp.org/en/jsr/detail?id=220" rel="nofollow">http://jcp.org/en/jsr/detail?id=220</a>] (JPA Specification)
</li></ul>
<!--
NewPP limit report
Preprocessor node count: 81/1000000
Post-expand include size: 0/2097152 bytes
Template argument size: 0/2097152 bytes
#ifexist count: 0/100
-->
<!-- Saved in parser cache with key wikidb:pcache:idhash:17885-0!1!0!!en!2!edit=0 and timestamp 20120203101551 -->
<div class="printfooter">
Retrieved from "<a href="RecordStorage.html">http://wiki.eclipse.org/SMILA/Specifications/RecordStorage</a>"</div>
<!-- end content -->
<div class="visualClear"></div>
</div>
</div>
</div>
<!-- Yoink of toolbox for phoenix moved up -->
</div>
</div>
<div id="clearFooter"/>
<div id="footer" >
<ul id="footernav">
<li class="first"><a href="http://www.eclipse.org/">Home</a></li>
<li><a href="http://www.eclipse.org/legal/privacy.php">Privacy Policy</a></li>
<li><a href="http://www.eclipse.org/legal/termsofuse.php">Terms of Use</a></li>
<li><a href="http://www.eclipse.org/legal/copyright.php">Copyright Agent</a></li>
<li><a href="http://www.eclipse.org/org/foundation/contact.php">Contact</a></li>
<li><a href="http://wiki.eclipse.org/Eclipsepedia:About" title="Eclipsepedia:About">About Eclipsepedia</a></li>
</ul>
<span id="copyright">Copyright &copy; 2012 The Eclipse Foundation. All Rights Reserved</span>
<p id="footercredit">This page was last modified 08:14, 13 May 2010 by <a href="http://wiki.eclipse.org/index.php?title=User:Spoon.reloaded.gmail.com&amp;action=edit" class="new" title="User:Spoon.reloaded.gmail.com"> </a>. Based on work by <a href="http://wiki.eclipse.org/User:Daniel.stucky.empolis.com" title="User:Daniel.stucky.empolis.com">Daniel Stucky</a> and <a href="http://wiki.eclipse.org/User:Tmenzel.brox.de" title="User:Tmenzel.brox.de">thomas menzel</a>.</p>
<p id="footerviews">This page has been accessed 2,584 times.</p>
</div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-910670-4");
pageTracker._trackPageview();
</script>
<!-- <div class="visualClear"></div> -->
<script type="text/javascript">if (window.runOnloadHook) runOnloadHook();</script>
</div>
<!-- Served in 0.439 secs. --></body></html>