I would like to use xml data source in jasper server (5.0.0). Xml files are created "on the fly" while application is running so different reports will have different xml data sources. I know that jasper server does not have XML data source defined but I found out that creating report without data source and then passing parameter XML_FILE - java.io.File will do the work. I managed to do this in java servlet:
jasperReport = JasperCompileManager.compileReport("path to jrxml");
HashMap map = new HashMap();
map.put("XML_FILE", new File(xmlSourceFile));
jasperPrint = JasperFillManager.fillReport(jasperReport,map);
byte [] o = JasperExportManager.exportReportToPdf(jasperPrint);
but unfortunately failed to do it on jasper server. I am using rest services to run report so I can use only String parameters. I've tried to write a scriptlet that converts String parameter with xml url to java.io.File
public class XmlScriplet extends JRDefaultScriptlet{
#Override
public void beforeReportInit(){
try {
String param = (String)this.getParameterValue("fileName");
HashMap map = new HashMap();
map.put("XML_FILE", new File(param));
this.parametersMap.putAll(map);
} ...
but this gives me an empty report.
Thank you in advance.
You can also pass any XML resource (be an static XML or even a REST service) by passing by simply "net.sf.jasperreports.xml.source" parameter to your report, if you are using Jasperreports Server 5.5, and assuming your report unit is named "report" and your xml data resource is in http://(host):(port)/resource.xml path, you might want to call the report using Jasper's REST v2 API like this:
http://(host):(port)/jasperserver/rest_v2/reports/path/to/your/report/unit/report.html?net.sf.jasperreports.xml.source=http://(host):(port)/resource.xml
In order to have a default "net.sf.jasperreports.xml.source" value in your report, You should also add the following in the "parameters" section in your report source jrxml
<parameter name="net.sf.jasperreports.xml.source" class="java.lang.String">
<defaultValueExpression><![CDATA["http://(host):(port)/resource.xml"]]> </defaultValueExpression>
</parameter>
Do not forget to add xpath2 query support to jasperreports server by appending:
# addition for xpath2 queries
net.sf.jasperreports.query.executer.factory.xpath2 = net.sf.jasperreports.engine.query.JRXPathQueryExecuterFactory
to /WEB-INF/classes/jasperreports.properties inside the deployed dir in the appserver
For more info about which parameters xml data source allows, you could also take a look at the official documentation
The JasperSoft Community wiki has two articles that will help explain some of the details.
Remote XML Datasource
Using XML Datasource in JasperReports server
You may need experiment with the XML_URL parameter to get your XML into the report.
Related
I have a JAX-RS web service which looks like so:
#Path("/status")
#Produces("application/xml")
#GET
public PrecisionStatus getPrecisionValue(){
PrecisionStatus status = ...
return status;
}
Initially, the result was:
<PrecisionStatus sensorID="TemperatureSensor5"><condition>OK</condition><fieldValue>60.0</fieldValue></PrecisionStatus>
It looks fine, but I want to declare the xsd file which describes this document. By using JAXB marshalling features, I was able to produce (in logger/console) the desired output:
<PrecisionStatus sensorID="TemperatureSensor5" xsi:noNamespaceSchemaLocation="http://mysite.com/myapp/xsd0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<condition>OK</condition>
<fieldValue>60.0</fieldValue>
</PrecisionStatus>
(this is confirmed by unmarshalling the object).
However, if i return this object return status;, the browser receives the former xml document, namely the one without the reference to xsd.
I am pretty sure that the object has the right form, but somewhat the reference to xsd is stripped in the final result. Any clue?
You could create a JAX-RS MessageBodyWriter to have access to the Marshaller in order to set the JAXB_NO_NAMESPACE_SCHEMA_LOCATION property. For a complete example see:
Formatted XML output in CXF?
I have to code a PHP front end for my Jasper reports. I could successfully connect to the server, authenticate and view the repositories using the jasper REST calls. However, when I try to access a report, I get the following error in the response body:
Report not found (uuid not found in session)
The php code is given below:
$uri = "http://localhost:8080/jasperserver/rest/report/samples/Client_Information_Report?RUN_OUTPUT_FORMAT=html";
//PUT request to run the report
$response = Httpful\Request::put($uri, $payload)
->authenticateWith("jasperadmin", "jasperadmin")
->send();
$xml = new SimpleXMLElement($response->body);
$uuid = (String)$xml->uuid; //The uuid is successfully returned
$uri = "http://localhost:8080/jasperserver/rest/report/$uuid?file=report";
$report = Httpful\Request::get($uri)
->authenticateWith("jasperadmin", "jasperadmin")
->send();
I am able to confirm that a uuid is returned with the first PUT. Is there anything I am missing here? Any help is appreciated.
Janenz,
First check the info that is coming from the PUT response to see if there is actually a report being generated and that is not empty, you should receive something like this:
<report>
<uuid>d7bf6c9-9077-41f7-a2d4-8682e74b637e</uuid>
<originalUri>/reports/samples/AllAccounts</originalUri>
<totalPages>43</totalPages>
<startPage>1</startPage>
<endPage>43</endPage>
<file type="image/png">img_0_0_0</file>
<file type="image/gif">px</file>
<file type="text/html">report</file>
<file type="image/jpeg">img_0_42_27</file>
<file type="image/png">img_0_42_26</file>
</report>
Notice the number of pages and the files available.
I have not used the Httpful library, but another thing to check is the way that library uses the Basic Authentication. It may happen that the second call is logging you in again and creating a new session; that is why you cannot find the UUID of the current session.
I have a full JasperServer and PHP sample in GitHub that you can check, it has the repository browsing and input control rendering implemented.
I'm not sure what version of JasperReports Server you are using but in the new version there is a new REST API that makes requesting reports a lot easier; check the JasperReports Server Web Services Guide (Section 3.2). I have that implemented in the JRS-Wrapper Branch of my project.
Hope this helps!!
MarianoL
I'm working on a project that aims to replace our current PDF generator with JasperReports Server. The plan is to use the REST/HTTP API to reach a high level of abstraction between the systems.
Optimally, we do not want to let JasperReports Server pull the data from the database, since this would bypass the existing logging and authorization in the calling application's architecture. Instead, we'd like to start with extracting the content in the calling application, and then pass that content to JasperReports Server.
We've done quite a bit of investigating, and the lack of relevant results indicates that this is not how you typically use JasperReports Server. The input parameters in the tutorials we've found are typically scalar values (integers, booleans or strings), and not complex structures or objects. Furthermore, it seems like more or less every sample assumes that you want to let JasperReports Server connect to a database.
If it's possible to pass in complex structures (like an array of maps, where some map elements are arrays or maps themselves), what's the best practice for doing this? I have no idea of how such a structure should be formatted in the request body. Is the SOAP API a better fit?
If this is not at all how you should design a JasperReports Server solution, what alternative products/solutions are more suitable?
Thanks in advance for any input.
After several hours spent on research, I think I'm ready to answer my own question.
JasperReports Server ("JRS" below) is fundamentally designed to fetch data by itself. Although it would be possible to force feed JRS with data, I've decided not to.
One of the most obvious drawback of not letting JRS fetch the data itself is that it would no longer be possible to generate reports from the JRS web interface. Integration from other systems also becomes impossible or difficult if the client application is responsible for supplying the data in a predefined format.
In the project I'm working on, we've decided to build a custom JRS DataSource based on the Remote XML DataSource, that invokes the client application's XML API. In other words, the client application requests a report from JRS, and JRS then requests it's data from the client application. The XML API will have to be expanded to cover all of our reporting needs, but that's a good thing in my opinion. Good API coverage will come in handy in the future.
I hope these thoughts helps someone having similar questions.
As you wrote, fetching data is more natural way for JRS. However, I needed to go the opposite way - I POST data to report sitting in JRS repo via a REST call.
I pass XML data in my parameter "xmlDocument" and, by means of a "trick", an executed report can use this XML for further X-path queries.
xmlDocument is just a simple String:
<parameter name="xmlDocument" class="java.lang.String">
<defaultValueExpression><![CDATA["<?xml version=\"1.0\" encoding=\"UTF-8\"?><documentData></documentData>"]]></defaultValueExpression>
</parameter>
At designing phase I create XML data adapter with XML file that I use for previewing. Note that a new parameter XML_INPUT_STREAM appeared after choosing XML adapter.
Then I publish the report to JRS.
During report execution, when the report is not linked to any data source, it reads XML_INPUT_STREAM parameter instead (as fallback data source), that looks as follows:
<parameter name="XML_INPUT_STREAM" class="java.io.InputStream" isForPrompting="false">
<defaultValueExpression><![CDATA[new java.io.ByteArrayInputStream($P{xmlDocument}.getBytes("UTF-8"))]]></defaultValueExpression>
</parameter>
I wrap "xmlDocument" string to InputStream.
Even if I agree with the answer, witch states that the JasperServer has been built to fetch data by itself, I had still to pass the data trough the rest API because it's the legacy way of my company to build Jasper reports and because we want to use custom Java services to fetch data.
I've found this described above to be the simpliest possible way to do this.
Having this simple custom pojo that you want to pass to the report trough web API:
public class CustomReport {
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public CustomReport() {
super();
}
1) Define a custom jasper scriptlet that has to be deployed on the server as a resource related to the report, witch will deserialize the string into the custom pojo object using GSON:
public class CustomScriptlet
extends JRDefaultScriptlet { public void afterReportInit()
throws JRScriptletException
{
Object customSerializedObj = getParameterValue("customSerialized");
if (customSerializedObj != null)
{
String customSerializedStr = customSerializedObj.toString();
if ((customSerializedStr != null) && (customSerializedStr.length() > 0))
{
CustomReport customReport = new Gson().fromJson(customSerializedStr,
CustomReport.class);
setVariableValue("customReport", customReport);
}
}
}
2) Use the parameter/variable with the custom scriptlet in jasper server:
<scriptlet name="Scriptlet_1" class="eu.dedalus.jasper.api.scriptlet.CustomScriptlet">
<scriptletDescription><![CDATA[CustomScriptlet]]></scriptletDescription>
</scriptlet>
<parameter name="customSerialized" class="java.lang.String"/>
<variable name="customReport" class="com.test.CustomReport" calculation="System"/>
3) Invoke the API # jasperserver/rest_v2/reportExecutions like this:
"reportUnitUri" : "/report/Custom_report",
"async":"false",
"outputFormat":"pdf",
"parameters" : {
"reportParameter" : [
{
"name": "customReport",
"value": ["{ \"content\" : \"test content\" } "]
}
]
}
I'm trying to access a REST service from a function written in the custom code of a report. I don't want to move that code into a separate assembly so the problem is around the custom code, please don't send me to custom assemblies.
Here's the code:
Public Shared Function GetData(ByVal id As String) As String
Dim strURL As String = ("http://..." & id)
Dim webRequest As System.Net.HttpWebRequest = DirectCast(System.Net.WebRequest.Create(strURL), System.Net.HttpWebRequest)
webRequest.Method = "Get"
Dim webResponse As System.Net.HttpWebResponse = DirectCast(webRequest.GetResponse, System.Net.HttpWebResponse)
Dim rdr As New System.IO.StreamReader(webResponse.GetResponseStream)
Return rdr.ReadToEnd
End Function
When I'm using it i receive the error:
System.Security.SecurityException: Request for the permission of type 'System.Net.WebPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.
at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet)
at System.Security.CodeAccessPermission.Demand()
at System.Net.HttpWebRequest..ctor(Uri uri, ServicePoint servicePoint)
at System.Net.HttpRequestCreator.Create(Uri Uri)
at System.Net.WebRequest.Create(Uri requestUri, Boolean useUriBase)
at System.Net.WebRequest.Create(String requestUriString)
at ReportExprHostImpl.CustomCodeProxy.GetData(String what, String id, String defaultValue)
The action that failed was:
Demand
The type of the first permission that failed was:
System.Net.WebPermission
The Zone of the assembly that failed was:
MyComputer
And I suppose that I may have future problems with System.IO too.
I had a look on CAS and I'm totally blurred, I don't know what policy file I have to change, what code group I have to change and how.
My understanding is that this is the code group used for custom code (in rssrvpolicy.config):
<CodeGroup
class="UnionCodeGroup"
version="1"
PermissionSetName="Execute"
Name="Report_Expressions_Default_Permissions"
Description="This code group grants default permissions for code in report expressions and Code element.>
<IMembershipCondition
class="StrongNameMembershipCondition"
version="1"
PublicKeyBlob="002400...CAEDDA2"
/>
</CodeGroup>
but simply setting the PermissionSetName to Fulltrust doesn't make any change.
For anyone experiencing this issue (a year and a half after the fact), if you are receiving this exception when trying to view the report from BIDS, then you need to update the RSPreviewPolicy.config file in your Visual Studio's PrivateAssemblies directory.
There are three security policy files that need to be modified for uses like this (custom code in expression or custom assemblies.) Detailed notes (including a seriously crucial one on where to place new CodeGroup elements!!) can be found on the MSDN page titled (as of today) "Using Reporting Services Security Policy Files". The security config files are the report server config (rssrvpolicy.config), the report manager config (rsmgrpolicy.config) and the report designer config (RSPreviewPolicy.config).
A great test for this is to update one at a time and test all three after each update (after deploying a report to your report server instance of course : ).
You should try PermissionSetName="FULLTRUST" in the codegroup.
I use CrystalReports 13 (13.0.2000.0) in an ASP.NET 4.0 application.
I need to export report in HTML because i want a static report page, without reporviewer that allows user interaction.
If i try the following code:
Source1.ReportDocument.ExportToHttpResponse(
CrystalDecisions.Shared.ExportFormatType.HTML32 /*or HTML40*/
, this.Response , false, "report");
Application generates an error (Detail: Export in HTTP response in HTML format is not supported.)
If i try ReportExporter, HTML32 and HTML40 are not available ase ExportFormat.
Can someone help?
Report can be viewed in HTML as
MemoryStream oStream; // using System.IO
oStream = (MemoryStream)
rd.ExportToStream(
CrystalDecisions.Shared.ExportFormatType.HTML40);
Response.Clear();
Response.Buffer = true;
Response.ContentType = "text/html";
Response.BinaryWrite(oStream.ToArray());
Response.End();
But the format may suffer.
Reference: How to Export Crystal Report in ASP.NET
Because you marked it up I thought I'd upgrade it to an answer for closure and the rep:
you could save the html document to disk and then use a redirect to that as a workaround but I can't find any other way of doing it. if you are going to do it that way make sure you add uniqueness to the fime name (I find datetime is a useful string) to support concurrency,
MD
Would pdf help (the examples that I have seen use pdf export)? if so that is easy to do but does require that your users have acrobat reader installed. From the error it seems that exporting to an http response in html format was not implemented at release but there may be a patch to fix it so try patching to latest version,
MD