Can anyone provide instructions on how to do this? I have several different JDBC DataSources set up and would like to be able to configure users to run the same report using different datasources. E.g. when user A logs in and runs report A, datasource 1 is used; when user B logs in and runs report A, datasource 2 is used. I am using version 4.0.
问题:
回答1:
I'm working with release 6.2 of JasperReports Server and this is perfectly possible, as users have attributes and you can reference these attributes in the datasource connection settings.
For example you would not set an specific ip for your DB host. Instead you would reference a user attribute (attributes can be defined for the user or inherited from organizations or the server itself):
host = {attribute('dbHost')}
or
host = {attribute('dbHost', 'User')}
The former tries to find the attribute in the whole hierarchy (User > Organization > Parent Organization > Server). The latter expects to find the attribute defined at user level.
You can find a complete explanation in section 4.1 of JasperReports Server Admin Guide and here:
http://community.jaspersoft.com/documentation/tibco-jasperreports-server-administrator-guide/v601/attributes-data-source-definitions
回答2:
There isn't a built-in functionality in JasperReports Server to do so. You would need to implement a Java Extension that would work as a wrapper for JDBC datasources. This wrapper would utilize either an existing connection selected per user or the user object itself to pass the required information to the datasource. This article might be for an earlier version but can guide you in the right direction.
More details on custom datasources in general you can also find in the samples/customDataSource folder in JasperReports Server installation (jasperserver-install-dir/samples)
回答3:
Something like this could be achieved by using a multi-tenant version of JasperReports Server. You would have 2 (or more) tenancies/companies, where users are assigned to a different company. When logging on the user will only see the reports/resources belonging to that company. That way you can have a different datasource per company, have the same reports setup in each company, but each report unit will point to the respective datasource. If you're worried about duplication of reports, but the common report JRXML resource files into a common folder that can be seen by both companies (eg at root level) and have the report units refer to these as sub-reports.
回答4:
It seems to be possible now, though maybe not per user but more per role. So you could set up a bunch of datasources, e.g. for roles admin, manager, user, guest and then use the appropriate datasource for the user.
Switching A DataSource Based On A User - JasperSoft Community Wiki
This example shows how to switch a JDBC data source per user using a custom data source in JasperReports Server. The example works with JasperReports Server version 3.5.1
\WEB-INF\applicationContext-customds.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <bean id="SwitcherDS" class="com.jaspersoft.ps.examples.SwitchingDataSourceFactory" > <property name="repositoryService"> <ref bean="repositoryService"/> </property> <property name="dataSourceServiceFactories"> <ref bean="dataSourceServiceFactories"/> </property> </bean> </beans>
A custom data source requires an implementation of the ReportDataSourceService interface
public void setReportParameterValues(Map parameterValues) { MetadataUserDetails userDetails = (MetadataUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); String userName = userDetails.getUsername(); // obtain a connection based on the username. String dataSourceURI = "/datasources/test2"; if (userName.equalsIgnoreCase("jasperadmin")) { dataSourceURI = "/datasources/ds_1"; } connection = getRepositoryDatasource(dataSourceURI); try { parameterValues.put(JRParameter.REPORT_CONNECTION, connection.getDataSource().getConnection()); } catch (SQLException sqle){ sqle.printStackTrace(); } }