Discussions
Categories
Groups
Community Home
Categories
INTERNAL ENABLEMENT
POPULAR
THRUST SERVICES & TOOLS
CLOUD EDITIONS
Quick Links
MY LINKS
HELPFUL TIPS
Back to website
Home
Intelligence (Analytics)
Is there any way to access BIRT DataEngine from inside a running report?
Yaytay
Hi,
I want to make use of two data sets from within a plugin.
It's entirely possible that BIRT will use the data sets elsewhere in addition to me using them, so I want to make use of BIRTs caching when I access them.
The way to do this seems to be to use the same DataEngine instance that BIRT is using (and the docs for DataEngine say that only one should usually exist), but I can't see any way to get hold of BIRT's DataEngine.
The context in which I need to access the engine is a fetch method on a ScriptedDataSetEventHandler, but if I can access the engine by any method I should be able to get it to that context.
Is it possible?
Thanks
Jim
Find more posts tagged with
Comments
mwilliams
Here's an example of using the Data Engine API within a report's script, from the devShare:
http://www.birt-exchange.org/org/devshare/designing-birt-reports/1542-data-engine-api-to-check-data-set-values/
Forty2
The Birt Data Engine is kept as a reference by the Execution Context which itself can only be accessed via java reflection since the reportContext only comes with a private reference to it.
However the IDataEngine implementation you need - the one that caches all data sets - is not instantiated until the ReportDocument is opened for writing (which happens after the Factory phase of the creation process) since all cached data is stored in the document.
The second issue is that the engine only caches data if the data set is used at least twice within the report i.e. is tied to a minimum of two report elements.
I'm making a guess here but I believe that in order to access the BIRT DataEngine you would have to make a few modifications to the source code yourself to work around these issues.
Yaytay
<blockquote class='ipsBlockquote' data-author="'Forty2'" data-cid="114993" data-time="1363090221" data-date="12 March 2013 - 05:10 AM"><p>
The Birt Data Engine is kept as a reference by the Execution Context which itself can only be accessed via java reflection since the reportContext only comes with a private reference to it.<br />
However the IDataEngine implementation you need - the one that caches all data sets - is not instantiated until the ReportDocument is opened for writing (which happens after the Factory phase of the creation process) since all cached data is stored in the document.<br />
The second issue is that the engine only caches data if the data set is used at least twice within the report i.e. is tied to a minimum of two report elements.<br />
I'm making a guess here but I believe that in order to access the BIRT DataEngine you would have to make a few modifications to the source code yourself to work around these issues.<br /></p></blockquote>
Thank you, that's really helpful.<br />
<br />
I've gone with creating a new DataEngine, but it would be nice to be able to share the cache.<br />
<br />
Jim
mwilliams
Yes, thanks for the post, Forty2. That is very good information!
Forty2
I've made some more progress on how to access the Birt Data Engine and just want to share the information. This post only applies if you're using seperate Run and Render Tasks.<br />
Attached is a patch that describes the small modification I had to make to the RunTask. It now opens the *.rptdocument earlier, so all data retrieved by the engine can be saved to the document. This is necessary because only then will the call to ExecutionContext.getDataEngine() return the right implementation.<br />
<br />
With that modification made, one can execute datasets in the manner described below:<br />
OnPrepare Skript:<br />
<pre class='_prettyXprint _lang-auto _linenums:0'>
importPackage(Packages.org.eclipse.birt.data.engine.api);
importPackage(Packages.org.eclipse.birt.data.engine.api.querydefn);
var executionContext = retrieveContext(..); //One way is to use Java Reflection
var ds = reportContext.getDesignHandle().findDataSet("Data Set");
var dataEngine = executionContext().getDataEngine();
var drs = dataEngine.getDTESession();
//Activates caching for all datasets
//The mode changes are required to avoid an exception
var dec = drs.getDataSessionContext().getDataEngineContext();
var mode = dec.getMode();
dec.setMode(DataEngineContext.DIRECT_PRESENTATION);
dec.setCacheOption(DataEngineContext.CACHE_USE_ALWAYS, -1);
dec.setMode(mode);
dataEngine.defineDataSet(ds);
var qd = new QueryDefinition();
qd.setDataSetName("Data Set");
qd.addInputParamBinding(<add one for each parameter>);
var pq = drs.prepare(qd);
var result = pq.execute(null);
//If the data should be cached the iterator must be retrieved!
var iterator = result.getResultIterator();
result.close();
</pre>
<br />
Cheers...!
Yaytay
<p>Hi Again,</p><p>I have to revisit my approach because the queries have:</p><ul class='bbc'><li>Parameters that reference the "params" object.</li><li>beforeOpen scripts that reference params and reportContext.</li><li>Computed columns that don't appear in the metadata.</li></ul><p>I think the first two of these issues should be solved by getting the right context the the query when it executes, but I can't figure out how to do that.</p><p> </p><p>My latest attempt, which I hoped would work, but doesn't, has:</p><pre class="_prettyXprint">ExecutionContext exeContext = ExecutionContextExtractor.extractExecutionContext(reportContext);scriptContext = exeContext.getScriptContext();scriptContext = scriptContext.newContext( new GlobalBIRT(exeContext) ); context = new DataSessionContext( DataSessionContext.MODE_DIRECT_PRESENTATION, dh, scriptContext, exeContext.getApplicationClassLoader() );...return preparedQuery.execute( (Scriptable)scriptContext.getScopeObject() );</pre><p>Anyone got any suggestions?</p><p> </p><p>Thanks</p><p> </p><p>Jim</p>
Yaytay
<p>Four hours last night googling away, trying things out, getting nowhere.</p><p>Half an hour this morning and I've found the answer
</p><p> </p><p>I couldn't find a single example of how to execute a query correctly, but eventually I found the source for <a data-ipb='nomediaparse' href='
https://eclipse.googlesource.com/birt/org.eclipse.birt/+/33e9cbc9cb0d56f0e7d41ecfc1edd248d19229b4/chart/org.eclipse.birt.chart.reportitem.ui/src/org/eclipse/birt/chart/reportitem/ui/DteAdapter.java'><span>org</span><span>.</span><span>eclipse</span><span>.</span><span>birt</span><span>.</span><span>chart</span><span>.</span><span>reportitem</span><span>.</span><span>ui</span></a><span><a
data-ipb='nomediaparse' href='
https://eclipse.googlesource.com/birt/org.eclipse.birt/+/33e9cbc9cb0d56f0e7d41ecfc1edd248d19229b4/chart/org.eclipse.birt.chart.reportitem.ui/src/org/eclipse/birt/chart/reportitem/ui/DteAdapter.java'>.DteAdapter</a>
, and that does it right.</span></p><p> </p><p><span>The trick is to <em>not</em> call execute on the preparedQuery itself, but instead to call it on the DataRequestSession.</span></p><p><span>The DataRequestSession takes in a ScriptContext both when it is constructed (via the DataSessionContext) and when execute is called.</span></p><p><span>This does leave the problem of how to get a ScriptContext, and I can't see any approach that is less ugly than using reflection on the ReportContext.</span></p><p> </p><p><span>For the benefit of this scenario it really would help if the ScriptContext could be obtained from the ReportContext via some sanctioned route.</span></p><p> </p><p><span>Rather than including all the source here, please go and look at the version on BitBucket (where you'll be able to see any changes I make in future, and see all the surrounding code too, if you want):</span></p><p><a data-ipb='nomediaparse' href='
https://bitbucket.org/yaytay/spudsoft-birt-dynamic-columns/src/2af8a1df2852ed81403db4bbf885597b2f305df9/SpudSoft BIRT Dynamic Columns/src/uk/co/spudsoft/birt/dynamic/columns/DynamicColumnsEventHandler.java?at=default'>https://bitbucket.org/yaytay/spudsoft-birt-dynamic-columns/src/2af8a1df2852ed81403db4bbf885597b2f305df9/SpudSoft BIRT Dynamic Columns/src/uk/co/spudsoft/birt/dynamic/columns/DynamicColumnsEventHandler.java?at=default</a></p><p> </p><p>A
small extract of the key bit to help people searching is:</p><pre class="_prettyXprint">ExecutionContext exeContext = ExecutionContextExtractor.extractExecutionContext(reportContext);scriptContext = exeContext.getScriptContext();scriptContext = scriptContext.newContext( new GlobalBIRT(exeContext) ); context = new DataSessionContext( DataSessionContext.MODE_DIRECT_PRESENTATION, dh, scriptContext, exeContext.getApplicationClassLoader() );session = DataRequestSession.newSession( context );...IPreparedQuery preparedQuery = session.prepare(queryDefn);return (IQueryResults)session.execute(preparedQuery, null, scriptContext);</pre><p>Jim</p>