HTTP Interface
Introduction
The xReporter server is a standalone application. To communicate with the server a HTTP interface is available, which will be described in this document. This HTTP interface will be used by other applications, and not by end-users in their web browser. The HTTP interface for the web browser will probably be very similar as far as URL's goes, but instead of the raw XML data produced by xReporter, it will need HTML pages.
What exactly is a HTTP interface? It basically boils down to having a set of URL-addressable resources, on which a limited number of operations are supported (mostly GET and POST), and which return as result of that operation a representation of the resource. The description of the HTTP interface will thus mostly consist of identifying the set of resources (and their URL's), the operations that are allowed on it, and the resulting representations.
The following resources exist within xReporter (they are described in more detail further on in this document):
- datasources
- reportcatalog
- reports
- reports/{id}: these are not the reports themselves, but report instances. A report instance itself provides the following subresources:
- step
- output
- qbe
- orderby
- columns
- url
- destroy (version >= 1.2.1)
- info (version >= 1.3)
- reportdefinitions
- savedreports
- savedreports/{name}
- savedreports/{id}
Each of these resources could take query parameters to refine their output, or parameters can be POSTed to them to modify the resource (in our case to configure the report instance).
The working of xReporter is user-dependent, thus the username should always be provided (as a parameter called "user"). xReporter assumes that the user is already authenticated by the presentation layer, and thus requires no password.
The working of xReporter is language and country dependent, therefore these must be provided with each request in the form of a "lang" parameter with as value "language-COUNTRY", for example "nl-BE" or "en-US".
HTTP is stateless (there are no user sessions), and thus so is the xReporter server. The state information that needs to maintained such as the user-provided parameters, the selected sort order, and so on are not stored in some user session but rather in the "report instance" resource.
Resource: datasources
Gives a list of available datasources. The result depends on the user.
The following request parameters are optional:
- supportsType if present, only datasources compatible with this datasource type will be returned
- compatibleWithReportDefinition if present, only datasources compatible with the datasource type required by this report definition will be returned
The supportsType and compatibleWithReportDefinition parameters cannot be used at the same time.
Example scenario (pseudo-HTTP):
--- request ---
GET /datasources?user=jef&lang=nl-BE
--- response ---
<xr:datasources xmlns:xr="http://outerx.org/xreporter/result/1.0">
<xr:datasource id="...">
<xr:name>...</xr:name>
<xr:description>...</xr:description>
</xr:datasource>
[and probably some more datasources]
</xr:datasources>
Resource: reportcatalog
Provides the catalog of reports.
Required parameters:
- dataSourceId the id of the desired data source, only reports compatible with this data source will be part of the output.
Example scenario (pseudo-HTTP):
--- request ---
GET /reportcatalog?user=jef&lang=nl-BE&dataSourceId=ds1
--- response ---
<xr:reportcatalog datasource-id="ds1"
xmlns:xr="http://outerx.org/xreporter/result/1.0">
<xr:catalog name="...">
<xr:report-definition id="..." name="..." description="..."/>
... more report-definition's ...
<xr:catalog name="...">
... more report-definition's and catalog's (recursive) ...
</xr:catalog>
</xr:catalog>
... more catalogs ...
</xr:reportcatalog>
Resource: reports
Containing resource for all report instances (see next section). Also serves as a factory for the creation of new report instances.
To create a new report instance, you need to do a POST with these parameters:
- reportId the ID of the report definition of which an instance should be created
- dataSourceId the ID of the datasource that should be used by the report
The response contains a link to the location of the created report instance.
Example scenario (pseudo-HTTP):
--- request --- POST /reports reportId=ln3&dataSourceId=ds2&user=jef&lang=nl-BE --- response --- <xr:link href="/reports/232" xmlns:xr="http://outerx.org/xreporter/result/1.0"/>
In addition to the reportId and dataSourceId parameters, additional parameters can be given to initialise the report further without additional calls to the (described below) subresources. See the section "Initialiasing a report in one go" further on for more information.
Resource: reports/{id} (= report instances)
Report instances are sub-resources of the "reports" resource and are identified by an ID. URL's of possible report instances are for example:
/reports/a_32423 /reports/a_2334 ...
A report instance provides a number of subresources:
- step
- output
- qbe
- orderby
- columns
A report instance has a certain number of states that need to be passed through in a certain order: first all interaction steps should be completed successfully, only after that the output can be retrieved.
A GET on a report instance gives a link to the current state of the report, for example:
--- request --- GET /reports/32?user=jef&lang=nl-BE --- response --- <xr:link href="/reports/32/step/step1" xmlns:xr="http://outerx.org/xreporter/result/1.0"/>
Resource: reports/{id}/step
This resource contains all the interaction steps that are necessary before the output of the report can be consulted. For the user, the interaction steps are about completing parameters and conditions, inside xReporter the steps can also trigger SQL statements and/or Java classes that create temporary tables.
For each interaction step, the step resource contains a subresource with as name the id of the step as defined in the report definition.
A GET on a particular step resource gives all information about the required parameters and conditions in that step, including datatypes, searchlists, and so on. If the step is currently not yet accessible (because other interaction steps need to be completed first), a link is returned to the current step.
Once the form for the interaction step has been completed, the parameters and conditions must be POSTed to the particular step resource. If everything is OK then a link is returned to the next step, or to the output if it was the last step. If validation errors occurred within the posted data, then all information about the required parameters and conditions will again be returned (as when doing a GET), together with information about the validation errors.
If a certain step is already completed, but a post is again done to the step, then the report instance state will be resetted from that step on and all interaction steps starting from that step will need to be run through again.
To submit a parameter, simply use a post-parameter with as name the id of the parameter and as value the value for the parameter. To submit a condition, there must be at least two post-parameters submitted: one with the selected operator, and one with the value. Since a condition can have multiple values, possibly multiple post-parameters must be submitted. Some examples:
Submit a parameter with id 'param1' and value 'hallo': param1=hallo Submit a condition with id 'cond1' and operator 'BETWEEN' and values '5' and '10': cond1.op=BETWEEN cond1.value.1=5 cond1.value.2=10
All parameters and conditions of a step should of course be posted in one time to the step.
Step XML format
Here the XML-format is described of the result of a GET operation on a step, or a POST in case there were validation problems.
<xr:report id="..." report-definition-id="..." datasource-id="..."
xmlns:xr="http://outerx.org/xreporter/result/1.0">
<xr:info>
<!-- xr:listener element versions >= 1.2.1 -->
<xr:listener>
<xr:instance-name>...</xr:instance-name>
<!-- host and port properties suppressed by default --->
<xr:host>...</xr:host>
<xr:port>...</xr:port>
</xr:listener>
<xr:datasource-name>...</xr:datasource-name>
<xr:time>...</xr:time>
<xr:report-name>...</xr:report-name>
<xr:report-description>...</xr:report-description>
<xr:user>
<xr:name>...</xr:name>
<xr:property name="..." value="..."/>
... more properties ...
</xr:user>
<xr:customer>...</xr:customer>
<xr:supports-qbe>...</xr:supports-qbe>
<xr:supports-orderby>...</xr:supports-orderby>
</xr:info>
<xr:step id="...">
<xr:parameter id="..." required="true|false">
<xr:value valid="true|false" validation-message="...">...</xr:value>
<!-- validation-message attribute only present if valid="false" -->
<xr:datatype>
<xr:prompt>...</xr:prompt>
<xr:title>...</xr:title>
<xr:operators>
<xr:operator id="..." description="..." argument-count="number|*"/>
... multiple operator elements ...
</xr:operators>
<!-- searchlist is optioneel -->
<xr:searchlist>
<xr:row>
<xr:value>...</value>
<xr:short-description>...</short-description>
<xr:long-description>...</long-description>
</xr:row>
... more row elements ...
</xr:searchlist>
</xr:datatype>
</xr:parameter>
<xr:condition id="..." required="true|false">
<xr:values>
<xr:value valid="true|false" validation-message="...">...</xr:value>
... possibly more value elements ...
</xr:values>
<xr:datatype>
<xr:prompt>...</xr:prompt>
<xr:title>...</xr:title>
<xr:operators>
<xr:operator id="..." description="..." argument-count="number|*"/>
... more operators ...
</xr:operators>
<!-- searchlist is optional -->
<xr:searchlist>
<xr:row>
<xr:value>...</value>
<xr:short-description>...</short-description>
<xr:long-description>...</long-description>
</xr:row>
... more row elements ...
</xr:searchlist>
</xr:datatype>
</xr:condition>
... more parameter and/or condition elements ...
</xr:step>
</xr:report>
The XML response of a step starts like all other XML responses of report instance specific resources with some metadata about the report instance. After that follows the step element which describes a series of parameters and/or conditions.
Resource: reports/{id}/output
The output-resource executes the query on the database and returns the result. Some metadata about the columns is also returned.
The output can be further refined by using extra query parameters:
- chunkOffset offset in the result of the query.
- chunkLength number of rows to return.
These parameters are optional. They could also have the value "-1", this has the same effect as not specifying them.
The XML format of the output is as follows (if the report has a database output).
<xr:report id="..." report-definition-id="..." datasource-id="..."
xmlns:xr="http://outerx.org/xreporter/result/1.0">
<xr:info>
<!-- xr:listener element versions >= 1.2.1 -->
<xr:listener>
<xr:instance-name>...</xr:instance-name>
<!-- host and port properties suppressed by default --->
<xr:host>...</xr:host>
<xr:port>...</xr:port>
</xr:listener>
<xr:datasource-name>...</xr:datasource-name>
<xr:time>...</xr:time>
<xr:report-name>...</xr:report-name>
<xr:report-description>...</xr:report-description>
<xr:user>
<xr:name>...</xr:name>
<xr:property name="..." value="..."/>
... more properties ...
</xr:user>
<xr:customer>...</xr:customer>
<xr:supports-qbe>true|false</xr:supports-qbe>
<xr:supports-orderby>true|false</xr:supports-orderby>
<xr:steps>
(This part includes information about all entered parameters or conditions
from the interaction steps.)
<xr:step id="...">
<xr:parameter id="">
<xr:value>...</xr:value>
<xr:title>...</xr:title>
<xr:type base="..."/>
</xr:parameter>
<xr:condition id="">
<xr:values>
<xr:value>...</xr:value>
... more values ...
</xr:values>
<xr:operator selected="(operator-id)" description="..."/>
<xr:natural-description>...</xr:natural-description>
<xr:title>...</xr:title>
<xr:type base="..."/>
</xr:condition>
</xr:step>
... more steps ...
</xr:steps>
(If there is a QBE, a description of the query will be inserted in the following element. Otherwise,
there will be no xr:qbe-description element)
<xr:qbe-natural-description>....</xr:qbe-natural-description>
<xr:first-step-with-interaction>...</xr:first-step-with-interaction>
</xr:info>
<xr:columns>
<xr:column field="..." id="...">
<xr:title>....</xr:title>
<xr:type base="string|long|bigdecimal|time|date|datetime"/>
</xr:column>
... more column elements ...
</xr:columns>
<xr:resultset>
<xr:row>
<xr:field raw="..." link="..."? linktitle="..."?>...</xr:field>
... more field elements ...
... optionally one or more link elements for the links not associated with columns ...
<xr:link link="..."? linktitle="..."?/>
[note that the link attribute is optional, it might be missing on rows on which the link
parameters have no values. In that case the link element merely serves as an alignment
element so that the xr:link elements on the same position on different rows correspond.]
</xr:row>
... more row elements ...
</xr:resultset>
</xr:report>
The columns element always contains as many column elements as there are field elements in the row elements (and in the same order of course).
The raw-attribute on the field element contains the "raw" (as in unformatted) value. The content of the field element contains the formatted value to show to the user.
The supports-qbe and supports-orderby metadata fields indicate whether Query By Example and order by are supported, so that navigation links to the QBE and order by pages can be enabled or disabled as needed.
In case the report does not retrieve its output from a database but from an external HTTP source, then there will be no xr:column and xr:resultset elements but instead the XML retrieved from the external source (which could be anything).
Resource: reports/{id}/qbe
The qbe resource contains the "Query By Example" functionality.
A GET on this resource gives a description of the QBE-grid (based on what's in the report definition). This consists of a set of conditions with a description of their datatype, and possibly the current state of the QBE.
A POST to this resource submits the QBE settings. If everything is OK, a l ink to the output resource is returned. If validation errors occurred, the description of the QBE grid will again be returned, now with information about the validation errors added.
From the moment the QBE settings are submitted, all requests on the output resource will take them into account, until the QBE settings are changed or reset.
Implementation-wise the QBE grid is nothing more than a collection of conditions (like the ones in the interaction steps). The id's of the conditions now consist of the id's of columns on which the QBE is applied, suffixed with " .1", ".2", ... for the various QBE lines. The rest remains the same, thus also what concerns the format in which to submit the conditions.
To reset the QBE settings, POST a parameter "reset=true" to the QBE resource.
The XML format of a GET on the QBE resource, or the result of a POST in case validation errors occurred:
<xr:report id="..." report-definition-id="..." datasource-id="..."
xmlns:xr="http://outerx.org/xreporter/result/1.0">
<xr:info>
<!-- xr:listener element versions >= 1.2.1 -->
<xr:listener>
<xr:instance-name>...</xr:instance-name>
<!-- host and port properties suppressed by default --->
<xr:host>...</xr:host>
<xr:port>...</xr:port>
</xr:listener>
<xr:datasource-name>...</xr:datasource-name>
<xr:time>...</xr:time>
<xr:report-name>...</xr:report-name>
<xr:report-description>...</xr:report-description>
<xr:user>
<xr:name>...</xr:name>
<xr:property name="..." value="..."/>
... more properties ...
</xr:user>
<xr:customer>...</xr:customer>
<xr:supports-qbe>true|false</xr:supports-qbe>
<xr:supports-orderby>true|false</xr:supports-orderby>
</xr:info>
<xr:qbe orientation="row|column">
<xr:qbe-line>
<xr:condition id="..." required="false">
... condition-description identical to the condition appearing
in a step ...
</xr:condition>
... more condition elements ...
</xr:qbe-line>
... more qbe-line elements ...
</xr:qbe>
</xr:report>
Resource: reports/{id}/orderby
A GET on this resource gives a list of the various sort order possibilities, and a POST on this resource configures the sort order. It is also possible to configure a non-predefined sort order.
To configure a predefined orderby, POST a parameter "orderby" with as value the ID of the selected order-choice.
To configure a custom sort order, a number of parameters should be posted of the form orderby.{seqnr}.column and orderby.{seqnr}.order. The part {seqnr} takes the values 1, 2, 3, and so on. The parameter ending on .column should contain the id of the column, the parameter ending on .order should contain " ASC" or "DESC" (but this parameter is optional).
The XML obtained by a GET on the orderby resource is as follows.
<xr:report id="..." report-definition-id="..." datasource-id="..."
xmlns:xr="http://outerx.org/xreporter/result/1.0">
<xr:info>
<!-- xr:listener element versions >= 1.2.1 -->
<xr:listener>
<xr:instance-name>...</xr:instance-name>
<!-- host and port properties suppressed by default --->
<xr:host>...</xr:host>
<xr:port>...</xr:port>
</xr:listener>
<xr:datasource-name>...</xr:datasource-name>
<xr:time>...</xr:time>
<xr:report-name>...</xr:report-name>
<xr:report-description>...</xr:report-description>
<xr:user>
<xr:name>...</xr:name>
<xr:property name="..." value="..."/>
... more properties ...
</xr:user>
<xr:customer>...</xr:customer>
<xr:supports-qbe>true|false</xr:supports-qbe>
<xr:supports-orderby>true|false</xr:supports-orderby>
</xr:info>
<xr:orderby-info>
<xr:orderby-choices selected="...">
<xr:orderby-choice id="...">
<xr:description>...</xr:description>
</xr:orderby-choice>
... more orderby-choice elements ...
</xr:orderby-choices>
<xr:columns>
<xr:column id="..." field="...">
<xr:title>....</xr:title>
<xr:type base="string|long|bigdecimal|time|date|datetime"/>
</xr:column>
... more column elements ...
</xr:columns>
</xr:orderby-info>
</xr:report>
If the user has configured a sort order himself (not from the predefined orderby's) then a temporary orderby-choice element will be added with id " custom", and the attribute "selected" of the orderby-choice element will thus also have the value "custom".
The part with the information on the columns serves for the case where the user wants to assemble its own orderby.
Resource: reports/{id}/columns
A GET on this resource gives an overview of the currently active column configuration.
A new column configuration can be specified by posting a series of parameters column.1, column.2, and so on with as value the id of a column. If a column id occurs multiple times then only the first occurrence is taken into account. The result of a POST is a link to the output.
To restore the column configuration to its original state, post a parameter reset with as value true.
The XML obtained by a GET on the columns resource is as follows.
<xr:report id="..." report-definition-id="..." datasource-id="..."
xmlns:xr="http://outerx.org/xreporter/result/1.0">
<xr:info>
<!-- xr:listener element versions >= 1.2.1 -->
<xr:listener>
<xr:instance-name>...</xr:instance-name>
<!-- host and port properties suppressed by default --->
<xr:host>...</xr:host>
<xr:port>...</xr:port>
</xr:listener>
<xr:datasource-name>...</xr:datasource-name>
<xr:time>...</xr:time>
<xr:report-name>...</xr:report-name>
<xr:report-description>...</xr:report-description>
<xr:user>
<xr:name>...</xr:name>
<xr:property name="..." value="..."/>
... more properties ...
</xr:user>
<xr:customer>...</xr:customer>
<xr:supports-qbe>true|false</xr:supports-qbe>
<xr:supports-orderby>true|false</xr:supports-orderby>
</xr:info>
<xr:columns>
<xr:current-configuration>
<xr:column id="..." field="...">
<xr:title>....</xr:title>
<xr:type base="string|long|bigdecimal|time|date|datetime"/>
</xr:column>
... more column elements ...
</xr:current-configuration>
<xr:available-columns>
<xr:column id="..." field="...">
<xr:title>....</xr:title>
<xr:type base="string|long|bigdecimal|time|date|datetime"/>
</xr:column>
... more column elements ...
</xr:available-columns>
</xr:columns>
</xr:report>
Initialiasing a report in one go
Instead of posting parameters to the individual subresources of the output resource, a report can also be fully initialised upon creation by specifying additional parameters when posting to the /reports resource. These parameters are essentially the same as the ones you would otherwise give to the subresources, but they are prefixed to avoid name collisions. These prefixes are:
- interact. for all parameters otherwise given to the step/... subresources
- orderby. for all parameters otherwise given to the orderby subresource
- qbe. for all parameters otherwise given to the qbe subresource
- column. for all parameters otherwise given to the columns subresource
If all goes well, after posting a call to /reports with all required parameters for the interaction steps, you will get a link to the output resource. Otherwise, you'll get an error. Note that date|datetime parameters must be initialized with a Long representation of the UTC date, as returned by System.currentTimeMillis(), for example.
It is possible to ask an existing report instance its URL with which it can be recreated, see the url subresource described below.
Resource: reports/{id}/url
A GET on this resource will return some XML containing a URL-path that can be used to fully recreate this report at any time. This URL is in fact a reference to the "/reports" resource with all necessary parameters to restore the report state in one time, without the need to do manual posts to all the different subresources (such as qbe, columns, ...). This URL can be used for various purposes: bookmarking, mailing to other persons, automated report fetching, ...
The URL does not contain the user and lang parameters, and does not contain the scheme and authority (= usually the hostname) parts.
<xr:report id="..." report-definition-id="..." datasource-id="..."
xmlns:xr="http://outerx.org/xreporter/result/1.0">
<xr:info>
[... the usual metadata ...]
</xr:info>
<xr:url>[... here comes the url ...]</xr:url>
</xr:report>
Resource: reports/{id}/destroy
Instead of allowing the report instance to expire naturally, one may force its immediate destruction with a GET or POST to this resource. A link to the /admin/reportinstances resource is returned. (version >= 1.2.1)
<xr:link xmlns:xr="http://outerx.org/xreporter/result/1.0" href="/admin/reportinstances" />
Resource: reports/{id}/info
Provides some minimal information on the report instance.
Resource: reportdefinitions/{id}
A GET on this resource returns the report definition XML file for which the id was specified. Note that the id is now a report definition id, not a report instance id.
This resource is provided for demonstrational and debugging purposes. Only users who have a user property called "$allow-definition-viewing" with value " yes" will be allowed to view report definitions.
Resource: savedreports
xReporter allows users to save their reports. The savedreports resource provides the interface to this.
A GET on this resource returns a list of saved reports. You can add a request parameter scope with as value "personal" (= default) or "public" to specify which saved reports should be included.
To save a report instance, one should do a POST to this resource with the following parameters:
- action should have the value "new"
- report-instance-id the id of the report instance to be saved
- name a name (usually entered by the user) under which this report should be saved
- overwrite if "true", and if a report with the given name already exists, it will be automatically overwritten.
- ispublic if "true" the saved report will be viewable and executable to all other xreporter users as well (provided they have the required rights on the implied datasource and report-definition)
- Additionally, all requests parameters whose name starts with "xrpfmtpref" will also be stored as part of the saved report. These parameters serve to store frontend-specific styling preferences.
Resource: savedreports/{name}
This resource represents a saved report. This resource enables you to run a saved report, and to delete it. Both of these operations are handled via POST, GET is currently not supported on this resource.
Running a (private) saved report
To run a saved report, do a post on this resource with the following parameter:
- action should have the value "createinstance"
After the report instance has been created, a link will be returned to the instance.
To use another data source than the one in the saved report, add an optional request parameter dataSourceId.
If the report was stored with format preferences (parameters starting with "xrpfmtpref"), then these will be added to the link in the query string. To avoid this, you can add a request parameter useSavedFormatPreferences="false".
Deleting a saved report
To delete a saved report, do a POST to this resource with the following parameter:
- action should have the value "delete"
After the report has been deleted, a link will be returned to the savedreports resource.
Toggle the 'public-private' property of a saved report
To change the 'is-public' property of a saved report, do a POST to this resource with the following parameter:
- action should have the value "makepublic" or "makeprivate" depending on what new value you want.
After the property has been updated, a link will be returned to the savedreports resource.
Resource: savedreportsById/{id}
This resource represents a saved report. This resource enables you only to run a saved report. To perform that action you should POST to it. GET is currently not supported on this resource.
Running a saved report
To run a saved report, do a post on this resource with the following parameter:
- action should have the value "createinstance"
After the report instance has been created, a link will be returned to the instance.
General errorhandling
In case of an error, a response of the following form is returned:
<xr:error xmlns:xr="http://outerx.org/xreporter/result/1.0"> <xr:description>an error message</xr:description> </xr:error>
In certain cases a general HTTP error is given withouth further explanation. This will however always be the consequence of incorrect use of the HTTP interface. For example, if one executes an operation that is not supported, such as POST on a resource that does not support this, a '405 Method not allowed' answer is given.
Lifetime of report instances
Report instances only live for a limited time. The exact time is configurable in xReporter's config.xml
Administrative resources
The following administrative resources are available:
- /admin/tests: triggers the running of unit tests within the Phoenix environment and shows the result of this. This is only used for unit tests that need to directly use certain xReporter components. Most of the unit tests however test the xReporter functionality via the HTTP interface. This tests can be invoked using the Ant buildscript.
- /admin/reportinstances: gives a list of all report instances currently alive inside xReporter.
- /admin/connectionproviderstatus: gives a list of all connectionpools with the number of connections that are in use and the number of available (pooled) connections.


There are no comments.