Browser JavaScript Function Reference
- 1 Introduction
- 2 Methods
- 2.1 Application Logging
- 2.2 Database
- 2.3 API - REST
- 2.4 API - Legacy
- 2.4.1 String runImportCSV(String import_type, String csv_data)
- 2.4.2 String runImportCSV_JSON(String import_type, String json_list_strings)
- 2.4.3 String runApiJSON(String request_type, String json_payload)
- 2.4.4 void runApiJSONAsync(String request_type, String payload, String callbackFunctionName)
- 2.4.5 void runImportCSVAsync(String import_type, String csv_data, String callbackFunctionName)
- 2.4.6 void runImportCSV_JSONAsync(String import_type, String json_list_strings, String callbackFunctionName)
- 2.5 Window
- 2.6 Client
- 2.6.1 String getCompanyName()
- 2.6.2 int getUserId()
- 2.6.3 String getUsername()
- 2.6.4 String getUserEmail()
- 2.6.5 Array getUsersGroupIDs()
- 2.6.6 String getPluginName()
- 2.6.7 String getModuleName()
- 2.6.8 int getObjectId()
- 2.6.9 boolean hasAccessRight(String name)
- 2.6.10 boolean savePluginDataByGroup(String group_name, String data_dictionary)
- 2.6.11 String getPluginData(String group_name, String key)
- 2.6.12 boolean deletePluginData(String group_name)
- 2.6.13 boolean reloadObject()
- 2.6.14 void hyperLink(String module, String param)
- 2.6.15 void runScheduledTask(String task_name)
- 2.7 Reporting
- 2.8 Printing
- 2.8.1 String localPrinters()
- 2.8.2 void printPDF(String printer_name, String pdf_base64_bytes, boolean show_print_dialog)
- 2.8.3 void printReportPDF(String printer_name, int copies, String report_id, String report_parameters, boolean throw_exception)
- 2.8.4 void printMergedReportsPDF(String printer_name, int copies, String report_dictionary_json)
- 2.8.5 void printMultipleReports_JasperReports(String report_dictionary_json, String printer_name)
- 2.8.6 void printZPL(String printer_name, String zpl_document)
- 2.9 File
- 2.10 Developer Tools
- 2.10.1 String listMethods()
- 3 Common Usage Patterns
- 4 Error Handling Best Practices
- 5 Performance Tips
- 6 Security Considerations
Introduction
Below is a comprehensive list of methods grouped by the resource they interact with. These methods are available to the page under the fb_client
object that is injected into the browser window. The PluginBrowserBridge provides the main JavaScript interface for Fishbowl applications to interact with the underlying Java system. This bridge enables web-based reports and applications to access database queries, API calls, file operations, reporting, printing, and window management directly from JavaScript.
All methods marked with @JsAccessible
can be called from JavaScript running in the browser component. Unfortunately, we are unable to interact with these methods using native objects. So passing complex data is done by serializing objects into JSON strings, and vice-versa.
Methods
Application Logging
void logInformation(String message)
Logs an informational message to the application log and console.
Parameters:
message
(String): The message to log
Example
fb_client.logInformation("Processing started for order 12345");
void logError(String message)
Logs an error message to the application log and console.
Parameters:
message
(String): The error message to log
Example
fb_client.logError("Failed to process order: Invalid customer ID");
String logMessages()
Returns all logged messages for the current page session.
Returns: String containing all logged messages
Example
const allLogs = fb_client.logMessages();
console.log(allLogs);
String serverLogMessages()
Retrieves server-side log messages.
Returns: String containing server log messages
Example
const serverLogs = fb_client.serverLogMessages();
Database
String runQuery(String sql)
Executes a SQL query without parameters and returns an array of records as JSON objects. If there is an error, it returns an object. Note: All result properties will be returned in lowercase.
Parameters:
sql
(String): SQL query to execute
Returns: JSON string containing query results or error information
Examples
Return a basic query with a single row.
var results = fb_client.runQuery("select * from company");
Return a basic query with multiple rows.
var results = fb_client.runQuery("select * from so limit 10");
What happens with a syntax error.
var results = fb_client.runQuery("select *, from so limit 10");
String runQueryParameters(String sql, String json_parameters)
Executes a SQL query with parameters to prevent SQL injection. Accepts a single object with parameters serialized as JSON. To define a parameter use :name
syntax, and use all lower case parameter names in SQL and in the JSON object.
Parameters:
sql
(String): SQL query with parameter placeholders (use:parameter_name
syntax)json_parameters
(String): JSON object containing parameter values
Returns: JSON string containing query results or error information
Examples
Query sales orders by a specific customer id.
var params = JSON.stringify({customer_id:5});
var results = fb_client.runQueryParameters("select * from so where customerid = :customer_id", params );
Advanced example with multiple parameters:
const sql = "SELECT * FROM so WHERE customerid = :customer_id AND dateissued >= :start_date";
const params = JSON.stringify({
customer_id: "123",
start_date: "2023-01-01"
});
const results = fb_client.runQueryParameters(sql, params);
const data = JSON.parse(results);
Error Response Example:
{
"is_error": true,
"error_msg": "SQL syntax error: ..."
}
void runQueryAsync(String sql, String callbackFunctionName)
Executes a SQL query asynchronously without parameters. The method returns immediately and executes the specified JavaScript callback function when the query completes.
Parameters:
sql
(String): SQL query to executecallbackFunctionName
(String): Name of the JavaScript function to call when the query completes
Returns: void (method returns immediately)
Callback Function: The callback function receives one parameter: the JSON result object (same format as synchronous runQuery
)
Example
// Define callback function
function handleAsyncResult(result) {
if (result.is_error) {
console.error("Query failed:", result.error_msg);
fb_client.dialogStatus("Query failed");
} else {
console.log("Query succeeded, rows:", result.length);
displayResults(result);
fb_client.dialogStatus("Data loaded");
}
}
// Execute async query
fb_client.dialogStatus("Loading data...");
fb_client.runQueryAsync("SELECT * FROM part WHERE activeflag = 1", "handleAsyncResult");
// Code continues immediately while query runs in background
console.log("Query started, continuing with other work...");
void runQueryParametersAsync(String sql, String json_parameters, String callbackFunctionName)
Executes a SQL query asynchronously with parameters. The method returns immediately and executes the specified JavaScript callback function when the query completes.
Parameters:
sql
(String): SQL query with parameter placeholders (use:parameter_name
syntax)json_parameters
(String): JSON object containing parameter valuescallbackFunctionName
(String): Name of the JavaScript function to call when the query completes
Returns: void (method returns immediately)
Callback Function: The callback function receives one parameter: the JSON result object (same format as synchronous runQueryParameters
)
Example
// Define callback function
function processCustomerOrders(result) {
if (result.is_error) {
console.error("Customer order query failed:", result.error_msg);
document.getElementById('orderStatus').textContent = 'Error loading orders';
return;
}
document.getElementById('orderStatus').textContent = `Found ${result.length} orders`;
// Process results
result.forEach(order => {
addOrderToTable(order);
});
fb_client.pbUpdate(100);
fb_client.logInformation(`Loaded ${result.length} orders for customer`);
}
// Execute async parameterized query
const customerId = document.getElementById('customerId').value;
const startDate = document.getElementById('startDate').value;
const sql = `
SELECT so.num, so.totalamount, so.dateissued, c.name as customer_name
FROM so
JOIN customer c ON so.customerid = c.id
WHERE so.customerid = :customer_id
AND so.dateissued >= :start_date
ORDER BY so.dateissued DESC
`;
const params = JSON.stringify({
customer_id: customerId,
start_date: startDate
});
fb_client.pbUpdate(25);
fb_client.dialogStatus("Loading customer orders...");
fb_client.runQueryParametersAsync(sql, params, "processCustomerOrders");
// Continue with other UI updates
updateCustomerInfo(customerId);
API - REST
String restApiCall(String method, String path, String body)
Makes HTTP REST API calls to the Fishbowl API server using the current authentication token. This is a BETA feature, and is not guaranteed to work correctly or break in the future. You can find REST swagger docs using the Fishbowl Server web port, reference: XXXX.
Parameters:
method
(String): HTTP method (GET, POST, PUT, DELETE)path
(String): API endpoint pathbody
(String): Request body (JSON string, null for GET requests)
Returns: JSON string with HTTP response details
Example
Get company information
var result = fb_client.restApiCall("GET","/company");
console.log(result);
Advanced Examples:
// GET request
const getResponse = fb_client.restApiCall("GET", "/api/part/1234", null);
const getData = JSON.parse(getResponse);
// POST request
const postData = JSON.stringify({
name: "New Part",
description: "Part description"
});
const postResponse = fb_client.restApiCall("POST", "/api/part", postData);
Response Format:
{
"http_code": "200",
"response": "API response data",
"is_error": false
}
void restApiCallAsync(String method, String path, String body, String callbackFunctionName)
Makes HTTP REST API calls asynchronously to the Fishbowl API server. The method returns immediately and executes the specified JavaScript callback function when the API call completes.
Parameters:
method
(String): HTTP method (GET, POST, PUT, DELETE)path
(String): API endpoint pathbody
(String): Request body (JSON string, null for GET requests)callbackFunctionName
(String): Name of the JavaScript function to call when the API call completes
Returns: void (method returns immediately)
Callback Function: The callback function receives one parameter: the JSON response object (same format as synchronous restApiCall
)
Example
// Define callback function
function handleApiResponse(response) {
const data = JSON.parse(response);
if (data.is_error) {
console.error("API call failed:", data.error_msg);
fb_client.dialogStatus("API error");
return;
}
console.log("HTTP Status:", data.http_code);
if (data.http_code === "200") {
const apiData = JSON.parse(data.response);
console.log("API Response:", apiData);
processApiData(apiData);
fb_client.dialogStatus("API call successful");
} else {
console.warn("Unexpected HTTP status:", data.http_code);
}
}
// Execute async GET request
fb_client.dialogStatus("Loading part data...");
fb_client.restApiCallAsync("GET", "/api/part/1234", null, "handleApiResponse");
API - Legacy
String runImportCSV(String import_type, String csv_data)
Creates and executes an ImportRequest, given a string of an import_type (Reference: Legacy Fishbowl CSV Import Reference ) and a CSV string. The method returns a JSON object as a string.
Parameters:
import_type
(String): Type of import (e.g., "Part", "Customer", "SalesOrder")csv_data
(String): CSV formatted data with headers
Returns: JSON string containing import results
Examples
Import a Custom Field Data Import
var csv = "";
var import_type = "ImportCustomFieldData";
var result = fb_client.runImportCSV(import_type, csv);
console.log(result);
> ""
Advanced Example:
const csvData = `"PartNumber","Description","UOM"
"TEST-001","Test Part 1","ea"
"TEST-002","Test Part 2","ea"`;
const result = fb_client.runImportCSV("Part", csvData);
const importResult = JSON.parse(result);
String runImportCSV_JSON(String import_type, String json_list_strings)
Imports data from a JSON array of CSV row strings.
Parameters:
import_type
(String): Type of importjson_list_strings
(String): JSON array of CSV row strings
Example
const csvRows = JSON.stringify([
'"TEST-001","Test Part 1","ea"',
'"TEST-002","Test Part 2","ea"'
]);
const result = fb_client.runImportCSV_JSON("Part", csvRows);
String runApiJSON(String request_type, String json_payload)
Executes a legacy API call given a request_type, (Reference: Legacy Fishbowl XML/JSON API Call Types ), and a JSON Payload. The internal Fishbowl Legacy API is XML, and Fishbowl will convert our JSON to XML, and on a completed request will convert XML to JSON.
Take note that there are some bugs with the XML<>JSON conversion, namely if a property is intended to be a list but has a single record/object, it will serialize as an object, and not a list. Reference: TBD.
Parameters:
request_type
(String): API call type (enum value from ApiCallType)payload
(String): JSON request payload
Returns: JSON string containing API response
Examples
var request = {};
var request_json = JSON.stringify(request);
var result_json = fb_client.runApiJSON("XXX",request_json);
var result = JSON.parse(result_json);
console.log(result);
> TBD
Advanced Example:
const request = JSON.stringify({
GetPartRq: {
Number: "ABC-123"
}
});
const response = fb_client.runApiJSON("GET_PART", request);
const data = JSON.parse(response);
void runApiJSONAsync(String request_type, String payload, String callbackFunctionName)
Executes legacy Fishbowl API requests asynchronously using XML/JSON conversion. The method returns immediately and executes the specified JavaScript callback function when the API call completes.
Parameters:
request_type
(String): API call type (enum value from ApiCallType)payload
(String): JSON request payloadcallbackFunctionName
(String): Name of the JavaScript function to call when the API call completes
Returns: void (method returns immediately)
Example
// Define callback function
function handleLegacyApiResponse(response) {
const data = JSON.parse(response);
if (data.is_error) {
console.error("Legacy API call failed:", data.error_msg);
fb_client.dialogStatus("API error");
return;
}
console.log("Legacy API Response:", data);
processLegacyApiData(data);
fb_client.dialogStatus("Legacy API call successful");
}
// Execute async legacy API call
const request = JSON.stringify({
GetPartRq: {
Number: "ABC-123"
}
});
fb_client.dialogStatus("Loading part via legacy API...");
fb_client.runApiJSONAsync("GET_PART", request, "handleLegacyApiResponse");
void runImportCSVAsync(String import_type, String csv_data, String callbackFunctionName)
Imports CSV data asynchronously using the legacy API. The method returns immediately and executes the specified JavaScript callback function when the import completes.
Parameters:
import_type
(String): Type of import (e.g., "Part", "Customer", "SalesOrder")csv_data
(String): CSV formatted data with headerscallbackFunctionName
(String): Name of the JavaScript function to call when the import completes
Returns: void (method returns immediately)
Example
// Define callback function
function handleImportResult(response) {
const data = JSON.parse(response);
if (data.is_error) {
console.error("CSV import failed:", data.error_msg);
fb_client.dialogStatus("Import failed");
return;
}
console.log("Import successful:", data);
fb_client.dialogStatus("Import completed successfully");
fb_client.reloadObject(); // Refresh the current view
}
// Execute async CSV import
const csvData = `"PartNumber","Description","UOM"
"TEST-001","Test Part 1","ea"
"TEST-002","Test Part 2","ea"`;
fb_client.dialogStatus("Starting CSV import...");
fb_client.pbUpdate(0);
fb_client.runImportCSVAsync("Part", csvData, "handleImportResult");
void runImportCSV_JSONAsync(String import_type, String json_list_strings, String callbackFunctionName)
Imports data asynchronously from a JSON array of CSV row strings. The method returns immediately and executes the specified JavaScript callback function when the import completes.
Parameters:
import_type
(String): Type of importjson_list_strings
(String): JSON array of CSV row stringscallbackFunctionName
(String): Name of the JavaScript function to call when the import completes
Returns: void (method returns immediately)
Example
// Define callback function
function handleJsonImportResult(response) {
const data = JSON.parse(response);
if (data.is_error) {
console.error("JSON CSV import failed:", data.error_msg);
fb_client.dialogStatus("Import failed");
return;
}
console.log("JSON import successful:", data);
fb_client.dialogStatus("JSON import completed successfully");
}
// Execute async JSON CSV import
const csvRows = JSON.stringify([
'"TEST-001","Test Part 1","ea"',
'"TEST-002","Test Part 2","ea"'
]);
fb_client.dialogStatus("Starting JSON CSV import...");
fb_client.runImportCSV_JSONAsync("Part", csvRows, "handleJsonImportResult");
Window
boolean dialogClose()
Closes the current browser window. Warning, the page execution will stop once the browser is closed.
Returns: Boolean (always true)
Example
var closing = fb_client.dialogClose();
void showStatusBar(boolean show)
Hides/Shows the status bar of the browser window, which includes a status label, and a small progress bar.
Parameters:
show
(Boolean): Whether to show the status bar
Examples
Show the status bar.
fb_client.showStatusBar(true);
Image TBD
Hide the status bar.
fb_client.showStatusBar(false);
Image TBD
void toggleFullscreen()
Toggles fullscreen mode for the dialog window.
Example
fb_client.toggleFullscreen();
void dialogStatus(String message)
Displays a short message in the status bar, approx. less than 100 characters.
Parameters:
message
(String): Status message to display
Example
fb_client.dialogStatus("Hello");
Image TBD
void pbUpdate(int value)
Controls the Progress Bar component in the status bar. Use whole integers for 0-100, and -1 for indeterminate progress.
Parameters:
value
(Integer): Progress value (0-100)
Examples
Set progress bar to 100%
fb_client.pbUpdate(100);
Image TBD
Set progress bar to 50%
fb_client.pbUpdate(50);
Image TBD
Set progress bar to indeterminate.
fb_client.pbUpdate(-1);
Image TBD
Advanced Progress Example:
for(let i = 0; i <= 100; i += 10) {
fb_client.pbUpdate(i);
// Perform work here
}
Client
String getCompanyName()
Gets the current company name from the database.
Returns: String company name
Example
Get the company name
var company_name = fb_client.getCompanyName();
console.log(company_name);
int getUserId()
Gets the current user's ID.
Returns: Integer user ID
Example
var user_id = fb_client.getUserId();
console.log(user_id);
> 1
String getUsername()
Gets the current user's username.
Returns: String username
Example
var user_name = fb_client.getUsername();
console.log(user_name);
> "admin"
String getUserEmail()
Gets the current user's email address from the database.
Returns: String email address
Example
var user_email = fb_client.getUserEmail();
console.log(user_email);
> "admin@example.com"
Array getUsersGroupIDs()
Gets the current user's group IDs.
Returns: Array of string group IDs
Example
const groupIds = fb_client.getUsersGroupIDs();
console.log("User groups:", groupIds);
String getPluginName()
Gets the current plugin name.
Returns: String plugin name
Example
const pluginName = fb_client.getPluginName();
console.log("Current plugin:", pluginName);
String getModuleName()
Gets the current module name from where it was launched.
Returns: String module name
Example
var module_name = fb_client.getModuleName();
console.log(module_name);
> "Sales Order"
int getObjectId()
Gets the current object ID. If the page is launched from a Module, like Sales Order module, it will return the current Module's ID, example, the Sales Order ID that is currently displayed. Returns a -1 if the Page is not launched from a Module.
Returns: Integer object ID
Example
var sales_order_id = fb_client.getObjectId();
// 5
Comprehensive User Info Example:
const userInfo = {
company: fb_client.getCompanyName(),
username: fb_client.getUsername(),
email: fb_client.getUserEmail(),
userId: fb_client.getUserId(),
groupIds: fb_client.getUsersGroupIDs(),
plugin: fb_client.getPluginName(),
module: fb_client.getModuleName(),
objectId: fb_client.getObjectId()
};
console.log("User Info:", userInfo);
boolean hasAccessRight(String name)
Checks if the current user has a specific access right.
Parameters:
name
(String): Access right name
Returns: Boolean indicating access
Example
if (fb_client.hasAccessRight("ViewInventory")) {
// Show inventory data
} else {
fb_client.logError("User lacks ViewInventory permission");
}
boolean savePluginDataByGroup(String group_name, String data_dictionary)
Saves data (JSON or Plain String) to the Fishbowl Plugin data tables (plugindata). The data dictionary is expected to be a JSON object (single level, no hierarchy). This data persists between sessions.
Parameters:
group_name
(String): Group identifierdata_dictionary
(String): JSON object containing key-value pairs
Returns: Boolean (always true)
Example
const data_to_store = "";
let my_dict = {
plugin_property: data_to_store
};
fb_client.savePluginDataByGroup('QuickOrderPage', JSON.stringify(my_dict));
Advanced Settings Example:
const settings = JSON.stringify({
theme: "dark",
autoRefresh: "true",
refreshInterval: "30"
});
fb_client.savePluginDataByGroup("user_preferences", settings);
String getPluginData(String group_name, String key)
Retrieves a string, given a group_name, and key.
Parameters:
group_name
(String): Group identifierkey
(String): Data key
Returns: String value or null if not found
Example
const plugin_val = fb_client.getPluginData('QuickOrderPage','plugin_property');
With Default Values:
const theme = fb_client.getPluginData("user_preferences", "theme") || "light";
boolean deletePluginData(String group_name)
Deletes plugin data by the group_name.
Parameters:
group_name
(String): Group identifier
Returns: Boolean (always true)
Example
fb_client.deletePluginData("user_preferences");
boolean reloadObject()
Reloads/refreshes the current modules object.
Returns: Boolean (always true)
Example
var refreshed = fb_client.reloadObject();
void hyperLink(String module, String param)
Launches a Fishbowl module by name, and if provided the param should open the record.
Parameters:
module
(String): Module name (e.g., "Picking", "SalesOrder", "Part")param
(String): Parameter value (usually an ID)
Example
Launch the Customer Module, and open Customer ID 5;
fb_client.hyperLink("Customer","5");
Pick Example: fb_client.hyperLink("Picking",String(PickID));
More Examples:
// Navigate to a specific pick
fb_client.hyperLink("Picking", "12345");
// Navigate to a sales order
fb_client.hyperLink("SalesOrder", "SO-2023-001");
void runScheduledTask(String task_name)
Runs a scheduled task by name.
Parameters:
task_name
(String): Name of the scheduled task
Example
fb_client.runScheduledTask("DailyInventorySync");
Reporting
void previewReport(String report_id, String report_parameters)
Opens a report preview window with the specified parameters.
Parameters:
report_id
(String): Report ID from the Fishbowl databasereport_parameters
(String): JSON object containing report parameters
Example
const params = JSON.stringify({
StartDate: "2023-01-01",
EndDate: "2023-12-31",
CustomerID: "123"
});
fb_client.previewReport("45", params);
String getReportPDF(String report_id, String report_parameters, boolean throw_exception)
Generates a PDF report and returns it as base64 encoded data.
Parameters:
report_id
(String): Report IDreport_parameters
(String): JSON object containing report parametersthrow_exception
(Boolean): Whether to throw exceptions on error
Returns: JSON string containing base64 PDF data or error information
Report Parameters by Type:
// Different parameter types supported
const params = JSON.stringify({
// String parameters
CustomerName: "ABC Company",
// Integer parameters
CustomerID: 123,
// Date parameters (yyyy-MM-dd format)
StartDate: "2023-01-01",
// Timestamp parameters (ISO format)
StartDateTime: "2023-01-01T00:00:00",
// Boolean parameters
IncludeInactive: false,
// Decimal parameters
MinAmount: 100.50
});
Example
const params = JSON.stringify({
StartDate: "2023-01-01",
EndDate: "2023-12-31"
});
const pdfResult = fb_client.getReportPDF("45", params, false);
const pdfData = JSON.parse(pdfResult);
if (!pdfData.is_error) {
// Use pdfData.pdf_bytes (base64 encoded PDF)
const blob = new Blob([atob(pdfData.pdf_bytes)], {type: 'application/pdf'});
const url = URL.createObjectURL(blob);
window.open(url);
} else {
fb_client.logError("Report generation failed: " + pdfData.message);
}
String getMergedReportsPDF(String report_dictionary_json)
Generates a merged PDF from multiple reports with specified copies.
Parameters:
report_dictionary_json
(String): JSON array of report definitions
Returns: Base64 encoded PDF string
Report Dictionary Format:
const reportDict = JSON.stringify([
{
report_id: "45",
copies: 1,
params: {
StartDate: "2023-01-01",
EndDate: "2023-12-31"
}
},
{
report_id: "46",
copies: 2,
params: {
CustomerID: "123"
}
}
]);
const mergedPdf = fb_client.getMergedReportsPDF(reportDict);
Printing
String localPrinters()
Gets a list of available local printers.
Returns: JSON string containing printer names
Example
const printersResult = fb_client.localPrinters();
const printers = JSON.parse(printersResult);
console.log("Available printers:", printers.printers);
// Display in a dropdown
const select = document.getElementById('printerSelect');
printers.printers.forEach(printer => {
const option = document.createElement('option');
option.value = printer;
option.textContent = printer;
select.appendChild(option);
});
void printPDF(String printer_name, String pdf_base64_bytes, boolean show_print_dialog)
Prints a PDF document to a specified printer.
Parameters:
printer_name
(String): Name of the printer (must match exactly)pdf_base64_bytes
(String): Base64 encoded PDF datashow_print_dialog
(Boolean): Whether to show print dialog
Example
const pdfBase64 = "JVBERi0xLjQKJeLjz9MKMSAwIG9iago8..."; // Base64 PDF data
fb_client.printPDF("HP LaserJet Pro", pdfBase64, false);
void printReportPDF(String printer_name, int copies, String report_id, String report_parameters, boolean throw_exception)
Prints a report directly to a printer without generating intermediate files.
Parameters:
printer_name
(String): Printer namecopies
(Integer): Number of copiesreport_id
(String): Report IDreport_parameters
(String): JSON report parametersthrow_exception
(Boolean): Whether to throw exceptions
Example
const params = JSON.stringify({
OrderID: "12345"
});
fb_client.printReportPDF("Label Printer", 2, "67", params, false);
void printMergedReportsPDF(String printer_name, int copies, String report_dictionary_json)
Prints a merged PDF of multiple reports.
Parameters:
printer_name
(String): Printer namecopies
(Integer): Number of copiesreport_dictionary_json
(String): JSON array of report definitions
void printMultipleReports_JasperReports(String report_dictionary_json, String printer_name)
Prints multiple reports using JasperReports engine.
Parameters:
report_dictionary_json
(String): JSON array of report definitionsprinter_name
(String): Printer name
void printZPL(String printer_name, String zpl_document)
Prints a ZPL (Zebra Programming Language) document to a label printer.
Parameters:
printer_name
(String): Printer namezpl_document
(String): ZPL formatted document
Example
const zplLabel = `
^XA
^FO20,20^A0N,25,25^FDPART NUMBER:^FS
^FO20,50^A0N,30,30^FDABC-123^FS
^FO20,90^A0N,25,25^FDQTY: 100^FS
^XZ
`;
fb_client.printZPL("Zebra ZT230", zplLabel);
File
String getResourceFileString(String filename)
Reads a text file from the working directory and returns its contents. Warning: We do check for path traversal.
Parameters:
filename
(String): Relative file path from working directory
Returns: String file contents or empty string on error
Security: File access is restricted to the working directory to prevent directory traversal attacks.
Example
Read a SQL file as a string.
var query_sql = fb_client.getResourceFileString("sql/test.sql");
Advanced Example:
const templateHtml = fb_client.getResourceFileString("templates/report_template.html");
if (templateHtml) {
document.getElementById('content').innerHTML = templateHtml;
} else {
fb_client.logError("Template file not found");
}
String getResourceFileAsBase64(String filename)
Retrieves a file name from the root page of the folder, as a Base64 string of bytes. Warning: We do check for path traversal.
Parameters:
filename
(String): Relative file path from working directory
Returns: Base64 encoded file contents or empty string on error
Example
Read an image file as Base64 string.
var image_b64 = fb_client.getResourceFileString("images/example.png");
console.log(image_b64);
# > .....
Advanced Example:
const imageData = fb_client.getResourceFileAsBase64("images/logo.png");
if (imageData) {
const imgElement = document.createElement('img');
imgElement.src = 'data:image/png;base64,' + imageData;
document.body.appendChild(imgElement);
}
void saveDataToFile(String title, String extension, String extension_description, String base64_data, String fileName, boolean openShell)
Shows a save dialog to save base64 data to a file. Displays a Java JFileChooser dialog so we can influence, control the window, and file filter in the dialog from JavaScript.
Parameters:
title
(String): Dialog titleextension
(String): File extension (e.g., "pdf", "xlsx")extension_description
(String): Extension description (e.g., "PDF Files")base64_data
(String): Base64 encoded file datafileName
(String): Default filename (optional)openShell
(Boolean): Whether to open file after saving (optional)
Example
Save a CSV.
var csv = "";
fb_client.saveDataToFile("Save CSV","csv","Excel (CSV)", btoa(csv) );
Advanced Example:
// Generate a report and save it
const pdfResult = fb_client.getReportPDF("45", "{}", false);
const pdfData = JSON.parse(pdfResult);
if (!pdfData.is_error) {
fb_client.saveDataToFile(
"Save Report",
"pdf",
"PDF Files",
pdfData.pdf_bytes,
"inventory_report.pdf",
true
);
}
Developer Tools
String listMethods()
Returns a list of all available JavaScript methods with their signatures.
Returns: JSON array of method signatures
Example
const methods = fb_client.listMethods();
const methodList = JSON.parse(methods);
console.log("Available methods:", methodList);
// Display methods in console for debugging
methodList.forEach(method => console.log(method));
Common Usage Patterns
1. Asynchronous Data Loading with Progress Updates
function loadLargeDatasetAsync() {
let loadedTables = 0;
const totalTables = 3;
function updateProgress() {
loadedTables++;
const progress = Math.round((loadedTables / totalTables) * 100);
fb_client.pbUpdate(progress);
if (loadedTables === totalTables) {
fb_client.dialogStatus("All data loaded successfully");
fb_client.logInformation("Async data loading completed");
}
}
function handlePartsData(result) {
if (result.is_error) {
fb_client.logError("Parts query failed: " + result.error_msg);
return;
}
displayPartsTable(result);
fb_client.logInformation(`Loaded ${result.length} parts`);
updateProgress();
}
function handleCustomersData(result) {
if (result.is_error) {
fb_client.logError("Customers query failed: " + result.error_msg);
return;
}
populateCustomerDropdown(result);
fb_client.logInformation(`Loaded ${result.length} customers`);
updateProgress();
}
function handleInventoryData(result) {
if (result.is_error) {
fb_client.logError("Inventory query failed: " + result.error_msg);
return;
}
updateInventoryChart(result);
fb_client.logInformation(`Loaded ${result.length} inventory records`);
updateProgress();
}
// Start all async queries simultaneously
fb_client.dialogStatus("Loading data...");
fb_client.pbUpdate(0);
fb_client.runQueryAsync("SELECT * FROM part WHERE activeflag = 1 LIMIT 1000", "handlePartsData");
fb_client.runQueryAsync("SELECT id, name FROM customer WHERE activeflag = 1", "handleCustomersData");
fb_client.runQueryAsync("SELECT * FROM qoh WHERE qty > 0", "handleInventoryData");
fb_client.logInformation("Started async loading of parts, customers, and inventory data");
}
2. Report Generation with User Parameters
function generateCustomerReport() {
const customerId = document.getElementById('customerId').value;
const startDate = document.getElementById('startDate').value;
const endDate = document.getElementById('endDate').value;
if (!customerId || !startDate || !endDate) {
fb_client.logError("All fields are required");
return;
}
const params = JSON.stringify({
CustomerID: parseInt(customerId),
StartDate: startDate,
EndDate: endDate
});
fb_client.pbUpdate(25);
fb_client.dialogStatus("Generating report...");
try {
const pdfResult = fb_client.getReportPDF("12", params, false);
const pdfData = JSON.parse(pdfResult);
fb_client.pbUpdate(75);
if (pdfData.is_error) {
fb_client.logError("Report generation failed: " + pdfData.message);
fb_client.dialogStatus("Report failed");
return;
}
fb_client.pbUpdate(100);
fb_client.dialogStatus("Report ready");
// Save the report
fb_client.saveDataToFile(
"Save Customer Report",
"pdf",
"PDF Files",
pdfData.pdf_bytes,
`customer_report_${customerId}_${startDate}_${endDate}.pdf`,
true
);
fb_client.logInformation("Customer report generated successfully");
} catch (error) {
fb_client.logError("Error generating report: " + error.message);
fb_client.dialogStatus("Error");
}
}
3. User Preferences with Defaults
function saveUserPreferences() {
const preferences = {
theme: document.getElementById('theme').value,
autoRefresh: document.getElementById('autoRefresh').checked.toString(),
refreshInterval: document.getElementById('refreshInterval').value,
dateFormat: document.getElementById('dateFormat').value
};
fb_client.savePluginDataByGroup("user_settings", JSON.stringify(preferences));
fb_client.logInformation("User preferences saved");
fb_client.dialogStatus("Settings saved");
}
function loadUserPreferences() {
const defaultPrefs = {
theme: "light",
autoRefresh: false,
refreshInterval: "30",
dateFormat: "MM/dd/yyyy"
};
// Load each preference with fallback to default
Object.keys(defaultPrefs).forEach(key => {
const value = fb_client.getPluginData("user_settings", key) || defaultPrefs[key];
const element = document.getElementById(key);
if (element) {
if (element.type === 'checkbox') {
element.checked = value === 'true';
} else {
element.value = value;
}
}
});
fb_client.logInformation("User preferences loaded");
}
Error Handling Best Practices
1. Always Parse and Check JSON Results
function safeQuery(sql) {
try {
const results = fb_client.runQuery(sql);
const data = JSON.parse(results);
if (data.is_error) {
fb_client.logError("Query failed: " + data.error_msg);
return null;
}
return data;
} catch (error) {
fb_client.logError("Error parsing query results: " + error.message);
return null;
}
}
2. Validate Parameters Before API Calls
function validateAndExecute(operation, params) {
// Validate required parameters
if (!params.customerId || !params.startDate) {
fb_client.logError("Missing required parameters");
return false;
}
// Validate data types
if (isNaN(parseInt(params.customerId))) {
fb_client.logError("Customer ID must be a number");
return false;
}
// Proceed with operation
return operation(params);
}
3. Use Try-Catch for All Bridge Operations
function safeReportGeneration(reportId, params) {
try {
fb_client.dialogStatus("Generating report...");
const result = fb_client.getReportPDF(reportId, JSON.stringify(params), false);
const data = JSON.parse(result);
if (data.is_error) {
throw new Error(data.message);
}
return data;
} catch (error) {
fb_client.logError("Report generation failed: " + error.message);
fb_client.dialogStatus("Report failed");
return null;
}
}
Performance Tips
Use Progress Updates: For long operations, update progress and status regularly
Batch Database Operations: Use parameterized queries for multiple similar operations
Cache Static Data: Store frequently accessed lookup data using plugin data storage
Validate Early: Check user inputs before making expensive API calls
Handle Large Results: Process large datasets in chunks to avoid memory issues
Use Async Methods: For long-running operations, use async methods to keep UI responsive
Security Considerations
SQL Injection Prevention: Always use
runQueryParameters()
instead of string concatenationAccess Control: Check user permissions with
hasAccessRight()
before sensitive operationsFile Security: File operations are restricted to the working directory
Input Validation: Validate all user inputs before processing
Error Information: Don't expose sensitive system information in error messages
This documentation provides a comprehensive guide for developers to build applications and reports using the PluginBrowserBridge interface. All methods marked with @JsAccessible
are available for use in JavaScript applications running within the Fishbowl browser component.