Overview
Application Scenario
When using a web service as a data source for your project, you may want reports to directly call the web service instead of defining a data connection to use the corresponding database table. This document describes how to implement this.
Implementation Method
You can use the Java program to access the web service, convert the data returned by the web service into a class dataset, and then use the dataset in the designer. In this example, the web service retrieves data through a Java Database Connectivity (JDBC) connection.
Example
In an Axis2 project, publish a web service. Then, write a Java class that calls the web service, and define the Java class as a class dataset in the designer.
Preparing the Web Service Data Source
Preparing the Axis2 Server
If you have set up an Axis2 server, skip this step.
1. Download and install the Java Development Kit (JDK) and a web application server to set up the deployment environment. This example uses Tomcat, which has been set up in advance.
2. Download the WAR distribution from the Axis2 official website.

3. Extract the deployment file and copy axis2.war to the Tomcat installation directory/webapps path. Start Tomcat. The axis2 folder is automatically generated in this path, as shown in the following figure.

4. After Tomcat starts, access the Axis2 service via a URL in a browser. If the page is accessible, the deployment is successful. This example uses a local server, so enter http://localhost:8080/axis2 in the browser.
Note: 
Writing a Java Class for Retrieving Data Through JDBC
Write a Java class to retrieve data through JDBC in a Java editor. Before compiling the class, import the corresponding JDBC database driver into the Java project. This example uses a MySQL database, so you need to import the MySQL JDBC driver first. For details, see Compiling a Java Program.
Note: package service; //The package name should be service, corresponding to the folder name used later.
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class MyService {
// Define database connection parameters.
private static final String DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver"; // Driver
private static final String URL = "jdbc:mysql://localhost:3306/z"; // z is the database name.
private static final String USERNAME = "root"; // Username
private static final String PASSWORD = "123456"; // Password
// Register the database driver.
static {
try {
Class.forName(DRIVER_CLASS_NAME);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
// Get a connection.
private static Connection getConn() throws SQLException {
return DriverManager.getConnection(URL, USERNAME, PASSWORD);
}
// Close the connection.
private static void closeConn(Connection conn) {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public List<String> get() throws SQLException { // The method must be declared as public to be accessed.
List<String> data = new ArrayList<>();
Connection connection = getConn();
Statement statement = connection.createStatement();
String sql = "select id,name from test"; // Define the SQL statement as needed.
data.add("id name");
try {
if (statement != null) {
ResultSet rs = statement.executeQuery(sql);
while (rs.next()) {
data.add(rs.getInt(1) + " " + rs.getString(2).trim());
}
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (statement != null) {
statement.close();
}
closeConn(connection);
} catch (Exception e) {
e.printStackTrace();
}
}
return data;
}
// Test
public static void main(String[] args) {
List<String> list;
MyService service = new MyService();
Connection conn = null; // Initialize the database connection variable.
try {
conn = MyService.getConn(); // Get a database connection and assign it to conn.
list = service.get(); // Retrieve data.
for (String s : list) {
System.out.println(s); // Display the retrieved data.
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (conn != null) {
closeConn(conn); // Close the connection conn.
}
}
}
}
After you compile the code successfully, the data queried from the database is displayed. In this example, data is queried from the test table. The MyService.class file is generated in the output path of the corresponding project.
Note: 
Publishing the Web Service
Create a services.xml file, and place it in Tomcat installation directory/webapps/axis2/META-INF. The content of services.xml is as follows:
<service name="MyService"> <!--You can customize the service name.-->
<description>
Web Service
</description>
<parameter name="ServiceClass">
service.MyService <!--The corresponding package name and class name-->
</parameter>
<operation name="get" > <!--Function name-->
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
class="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
</operation>
</service>
2. Package the compiled service class into an AAR file: Create a WS folder, and create two subfolders named META-INF and service in it, as shown in the following figure.

Place the services.xml file prepared in step one in the META-INF folder and the MyService.class file prepared in the "Writing a JDBC Class for Data Retrieval" section in the service folder, as shown in the following figure.

3. Package the WS folder to generate an AAR file. In Windows Command Prompt, use the cd command to go to the directory where the WS folder is located, and run the following command to generate the ws.aar file, as shown in the following figure.
jar cvf ws.aar .

You can find the ws.aar file in the WS folder, as shown in the following figure.

4. Copy ws.aar to Tomcat installation directory/webapps/axis2/WEB-INF/services, and start Tomcat. Then you can call the web service.
After the startup succeeds, access http://localhost:8080/axis2/services/MyService?wsdl. If the following page is displayed, the web service is published successfully.

Defining a Class Data Source
You have prepared the web service data source in the "Preparing the Web Service Data Source" section. Next, write a Java class that extends AbstractTableData, retrieves data through JDBC, and converts the retrieved data into a class dataset.
Preparing the Compilation Environment
Before compiling the program, you need to create a Java project environment and prepare a Java editor (for example, Eclipse or IntelliJ IDEA).
Import the JAR files of your FineReport project into the editor. The JAR files include:
All files in FineReport installation directory/lib
All files in FineReport installation directory/server/lib
All files in FineReport installation directory/webapps/webroot/WEB-INF/lib
tools.jar in JDK installation directory/lib
JAR files in the lib folder from the Axis2 binary distribution
Download the binary distribution from the Axis2 official website. After extracting the file, import the JAR files in the lib folder into the Java project. For details, see Compiling a Java Program.

Writing the Java Program
Create the WebServiceWSDLDataDemo.java file in the editor. The complete code is as follows:
Note: package com.fr.data;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.fr.general.data.TableDataException;
import com.fr.log.FineLoggerFactory;
import org.apache.axiom.om.*;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
public class WebServiceWSDLDataDemo extends AbstractTableData {
private String[][] data;
public WebServiceWSDLDataDemo() {
this.data = getWSDLData();
}
public int getColumnCount() throws TableDataException {
return data[0].length;
}
// Gets column names from the first row of the array.
public String getColumnName(int columnIndex) throws TableDataException {
return data[0][columnIndex];
}
// Gets the row count by subtracting 1 from the data length.
public int getRowCount() throws TableDataException {
return data.length - 1;
}
// Gets values.
public Object getValueAt(int rowIndex, int columnIndex) {
return data[rowIndex + 1][columnIndex];
}
// Retrieves data.
private static String[][] getResults(OMElement element) {
if (element == null) {
return null;
}
Iterator iterator = element.getChildElements();
List<String> list = new ArrayList<>();
while (iterator.hasNext()) {
OMNode omNode = (OMNode) iterator.next();
if (omNode.getType() == OMNode.ELEMENT_NODE) {
OMElement omElement = (OMElement) omNode;
if (omElement.getLocalName().equals("return")) {
String temp = omElement.getText().trim();
list.add(temp);
}
}
}
String[] result1 = list.toArray(new String[list.size()]);
String results[][] = new String[result1.length][2]; // The number of columns depends on the number of retrieved columns, and the number of rows depends on the amount of retrieved data.
String b1, b2;
for (int i = 0; i < result1.length; i++) {
if (result1[i].length() != 0) {
b1 = result1[i].substring(0, result1[i].indexOf(" "));
b2 = result1[i].substring(result1[i].indexOf(" ") + 1);
results[i][0] = b1;
results[i][1] = b2;
}
}
return results;
}
// Gets the connection and retrieves data.
private static String[][] getWSDLData() {
try {
String url = "http://localhost:8080/axis2/services/MyService?wsdl"; // This URL is the address of the published web service.
EndpointReference targetEPR = new EndpointReference(url);
// Creates an OMFactory for creating the namespace, method, and parameters below.
OMFactory fac = OMAbstractFactory.getOMFactory();
// Namespace
OMNamespace omNs = fac.createOMNamespace("http://service", "a");
// Method
OMElement method = fac.createOMElement("get", omNs); // Corresponding method name.
// Parameters
Options options = new Options();
options.setTo(targetEPR);
options.setAction("http://service/get");
// Builds the request.
ServiceClient sender = new ServiceClient();
sender.setOptions(options);
// Sends the request.
OMElement result1 = sender.sendReceive(method);
return getResults(result1);
} catch (org.apache.axis2.AxisFault e) {
FineLoggerFactory.getLogger().error(e, e.getMessage());
}
return null;
}
// Test
public static void main(String[] args) {
String[][] result = getWSDLData();
if (result != null) {
int col = result[0].length;
for (String[] aResult : result) {
for (int j = 0; j < col; j++) {
System.out.print(aResult[j] + " ");
}
System.out.println();
}
}
}
}
Compiling the Java File
After writing the Java file, compile WebServiceWSDLDataDemo.java in the editor. After compilation succeeds, the editor displays the retrieved data, and the WebServiceWSDLDataDemo.class file is generated in the corresponding project directory, as shown in the following figure.

Copy the compiled WebServiceWSDLDataDemo.class file to FineReport installation directory/webapps/webroot/WEB-INF/classes/com/fr/data, as shown in the following figure.
Note: 
Creating a Class Dataset
Copy the JAR files in the lib folder of Axis2 downloaded in the "Preparing the Compilation Environment" section to FineReport installation directory/webapps/webroot/WEB-INF/lib of the report project, excluding the log4j JAR file because it causes a conflict. After the files are copied, restart the report project so that the third-party JAR files can be loaded, as shown in the following figure.

2. Create a template, click the
icon above Template Dataset, select Class to open the Class Dataset window, and select the required class file, as shown in the following figure.

After selecting the class file, click OK to complete the class dataset configuration.
Using the Class Dataset
After the class dataset is configured, drag data columns to cells to bind the data, as you do with other datasets, as shown in the following figure.
Note: 