Skip to content

Lucas-Technology-Services/FastBI-App-SDK-Java21

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FastBI App SDK for Java

A Java 21 client SDK for the FastBI API — a Business Intelligence platform with KPI management, AI-powered analytics, MCP orchestration, real-time streaming, and multi-format report export.

Note on Authentication: The FastBI API uses short-lived JWT tokens (10-minute TTL) issued via client_id + secret. The SDK obtains and refreshes tokens automatically. OAuth 2.0 support will be added in a future release.

Requirements

  • Java 21 or later
  • Maven 3.8+
  • A running FastBI API instance

Installation

Add the dependency to your pom.xml:

<dependency>
    <groupId>io.fastbi</groupId>
    <artifactId>fastbi-app-sdk-java</artifactId>
    <version>0.1.0</version>
</dependency>

Quick Start

import io.fastbi.sdk.FastBiClient;
import io.fastbi.sdk.FastBiConfig;
import io.fastbi.sdk.kpi.Kpi;

FastBiClient client = FastBiClient.create(
    FastBiConfig.builder()
        .baseUrl("https://your-fastbi-instance.com/api/v1")
        .clientId("your-client-id")
        .secret("your-secret")
        .build()
);

// The client automatically obtains and refreshes tokens.
Kpi kpi = client.kpis().get("REVENUE_GROWTH", "Acme Corp");
System.out.printf("Current: %.2f / Target: %.2f%n", kpi.getCurrentValue(), kpi.getTargetValue());

Configuration

Property Type Default Description
baseUrl String http://localhost:3050/api/v1 FastBI API root URL
clientId String API client identifier
secret String API client secret
timeout Duration 30s Per-request timeout (does not apply to SSE streams)
httpClient HttpClient default (10 s connect timeout) Override for custom TLS, proxy, or testing

Spring Boot Integration

Add the dependency (same as above) and configure application.yml:

fastbi:
  base-url: https://your-fastbi-instance.com/api/v1
  client-id: your-client-id
  secret: your-secret
  timeout: 30s

A FastBiClient bean is registered automatically. Inject it where needed:

@Service
public class ReportingService {

    private final FastBiClient fastBi;

    public ReportingService(FastBiClient fastBi) {
        this.fastBi = fastBi;
    }

    public Kpi getKpi(String code, String org) {
        return fastBi.kpis().get(code, org);
    }
}

Authentication

Tokens are obtained automatically before the first authenticated request and refreshed 30 seconds before expiry. You can also manage tokens explicitly:

// Generate a token explicitly
TokenResponse tok = client.auth().generateToken("my_client", "my_secret");
System.out.println("Expires at: " + tok.getExpiresAt());

// Validate an existing token
ValidateResponse result = client.auth().validateToken(someToken);
System.out.println("Status: " + result.getStatus()); // "AUTHORIZED"

Services

KPIs — client.kpis()

// Create
Kpi kpi = client.kpis().create(CreateKpiRequest.builder()
    .code("NET_MARGIN")
    .name("Net Profit Margin")
    .organizationName("Acme Corp")
    .category("financial")
    .currentValue(18.5)
    .targetValue(22.0)
    .unit("%")
    .reportingPeriod("quarterly")
    .build());

// Read
Kpi kpi = client.kpis().get("NET_MARGIN", "Acme Corp");

// Update
Kpi updated = client.kpis().update("NET_MARGIN", UpdateKpiRequest.builder()
    .organizationName("Acme Corp")
    .currentValue(19.1)
    .build());

// Delete
client.kpis().delete("NET_MARGIN", "Acme Corp");

// List with filters
KpiListResponse list = client.kpis().list("Acme Corp", KpiListFilter.builder()
    .category("financial")
    .limit(20)
    .orderBy("created_at")
    .orderDir("DESC")
    .build());

// History
KpiHistoryResponse history = client.kpis().history("NET_MARGIN", "Acme Corp", 50, 0);

Analytics — client.analytics()

// Revenue insights with optional date/category/region filters
Map<String, Object> insights = client.analytics().revenueInsights(
    RevenueInsightsFilter.builder()
        .startDate("2025-01-01")
        .endDate("2025-12-31")
        .region("southeast")
        .build());

// Revenue forecast
Map<String, Object> forecast = client.analytics().forecastRevenue(
    ForecastRequest.builder()
        .organizationName("Acme Corp")
        .monthsAhead(6)
        .includeExternalFactors(true)
        .build());

// Product mix optimization
Map<String, Object> mix = client.analytics().optimizeProductMix(
    ProductMixRequest.builder()
        .organizationName("Acme Corp")
        .build());

Dashboards — client.dashboards()

// Create a global template
DashboardTemplate tmpl = client.dashboards().createTemplate(
    CreateDashboardTemplateRequest.builder()
        .name("Executive Overview")
        .description("C-level KPI dashboard")
        .build());

// Create an organization dashboard from the template
Dashboard dash = client.dashboards().create(CreateDashboardRequest.builder()
    .name("Q4 Executive Dashboard")
    .organizationName("Acme Corp")
    .templateId(tmpl.getId())
    .build());

// Add a widget
Widget widget = client.dashboards().addWidget(dash.getSlug(), AddWidgetRequest.builder()
    .title("Revenue Trend")
    .type("line_chart")
    .config(Map.of("metric", "REVENUE_GROWTH", "period", "12m"))
    .build());

Database Connections — client.connections()

// Register a connection
client.connections().register(RegisterConnectionRequest.builder()
    .organizationName("Acme Corp")
    .connectionName("prod-db")
    .host("db.example.com")
    .port(5432)
    .databaseName("analytics")
    .username("reader")
    .password("s3cr3t")
    .dbType(DbType.POSTGRES)
    .sslMode("require")
    .build());

// Execute a query
Map<String, Object> rows = client.connections().executeQuery("prod-db",
    ExecuteQueryRequest.builder()
        .organizationName("Acme Corp")
        .query("SELECT product, SUM(revenue) FROM sales GROUP BY product LIMIT 10")
        .useCache(true)
        .cacheTtlSeconds(300)
        .build());

Reports — client.reports()

// Create a report run
ReportRun run = client.reports().createRun(CreateRunRequest.builder()
    .templateName("monthly-financial")
    .organizationName("Acme Corp")
    .build());

// Advance through lifecycle stages
client.reports().transitionRun(run.getCreatedAt(),
    TransitionRunRequest.builder().targetStage("in_review").build());

// Approve review
client.reports().approveReview(run.getId(), ApproveReviewRequest.builder()
    .approvedBy("cfo@acme.com")
    .build());

// Schedule recurring reports
ReportSchedule schedule = client.reports().createSchedule(CreateScheduleRequest.builder()
    .name("monthly-close")
    .templateName("monthly-financial")
    .cronExpr("0 6 1 * *")   // 06:00 on the 1st of every month
    .build());

// Generate AI narrative
Map<String, Object> narrative = client.reports().generateNarrative(
    GenerateNarrativeRequest.builder()
        .runId(run.getId())
        .organizationName("Acme Corp")
        .language("en")
        .build());

Exports — client.exports()

// Export to Excel
client.exports().exportExcel(runId,
    ExcelExportRequest.builder().organizationName("Acme Corp").build());
String excelUrl = client.exports().downloadExcelUrl(runId);

// Export to CSV
client.exports().exportCsv(createdAt,
    CsvExportRequest.builder().organizationName("Acme Corp").build());

// Render a brand-aware PDF
client.exports().renderPdf(runId, PdfRenderRequest.builder()
    .organizationName("Acme Corp")
    .brandName("acme-brand")
    .build());
String pdfUrl = client.exports().downloadPdfUrl(runId);

Revenue Reports — client.revenue()

Map<String, Object> exec   = client.revenue().executiveReport();
Map<String, Object> region = client.revenue().regionalReport("southeast");
Map<String, Object> bu     = client.revenue().businessUnitReport("retail");
Map<String, Object> ts     = client.revenue().timeSeries("Acme Corp", "2025-01-01", "2025-12-31");

Gross Margin — client.grossMargin()

Map<String, Object> overall  = client.grossMargin().overall();
Map<String, Object> byProd   = client.grossMargin().byProduct();
Map<String, Object> byTier   = client.grossMargin().byCustomerTier();
Map<String, Object> forecast = client.grossMargin().forecast();

Sales AI — client.sales()

// Natural language question
Map<String, Object> answer = client.sales().ask(AskQuestionRequest.builder()
    .question("What are our top 3 revenue drivers this quarter?")
    .organizationName("Acme Corp")
    .build());

// Trend prediction
Map<String, Object> trend = client.sales().predictTrend(PredictSalesTrendRequest.builder()
    .organizationName("Acme Corp")
    .monthsAhead(3)
    .region("southeast")
    .build());

Machine Learning — client.ml()

// Train a linear regression model
client.ml().trainLinearRegression(TrainLinearRegressionRequest.builder()
    .features(List.of(List.of(1.0, 2.0), List.of(3.0, 4.0)))
    .labels(List.of(10.0, 20.0))
    .build());

// Single prediction
Map<String, Object> pred = client.ml().predictLinearRegression(
    PredictLinearRegressionRequest.builder()
        .features(List.of(5.0, 6.0))
        .build());

Accounting — client.accounting()

// Create a tax workflow template
AccountingTemplate tmpl = client.accounting().createTemplate(
    CreateAccountingTemplateRequest.builder()
        .name("ICMS Monthly")
        .category("tax")
        .structure(Map.of("steps", List.of("collect", "calculate", "file")))
        .build());

// Instantiate a workflow for a fiscal year
Map<String, Object> wf = client.accounting().createWorkflowFromTemplate(
    CreateWorkflowFromTemplateRequest.builder()
        .templateName("ICMS Monthly")
        .templateCategory("tax")
        .fiscalYear(2025)
        .build());

// Compliance calendar
Map<String, Object> calendar = client.accounting().getComplianceCalendar("2025");

AI Analysis — client.ai()

Pure statistical analysis and RAG — no external LLM calls.

// Customer intelligence
Map<String, Object> atRisk   = client.ai().identifyAtRiskCustomers();
Map<String, Object> segments = client.ai().getCustomerSegments();

// Financial analysis
Map<String, Object> cogs   = client.ai().getCogsBreakdown();
Map<String, Object> leaks  = client.ai().getMarginLeaks();

// KPI intelligence
Map<String, Object> devs = client.ai().getKpiDeviations();
Map<String, Object> corr = client.ai().correlateKpis();

// Product portfolio
Map<String, Object> bcg   = client.ai().getBcgMatrix();
Map<String, Object> under = client.ai().getUnderperformingProducts();

// Organization health
Map<String, Object> score = client.ai().getOrganizationHealthScore();

// Automotive (fleet management)
Map<String, Object> fleet   = client.ai().getFleetUtilization();
Map<String, Object> overdue = client.ai().getOverdueRentals();

MCP Orchestration — client.mcp()

// Full analysis across all dimensions
Map<String, Object> result = client.mcp().fullAnalysis(McpAnalyticsRequest.builder()
    .organizationName("Acme Corp")
    .startDate("2025-01-01")
    .endDate("2025-12-31")
    .maxSkills(6)
    .build());

// Route a natural language query
Map<String, Object> route = client.mcp().routeQuery(McpRouteQueryRequest.builder()
    .query("which KPIs are below target this quarter?")
    .topK(5)
    .build());

// Execute a high-level goal
Map<String, Object> goal = client.mcp().executeGoal(McpExecuteGoalRequest.builder()
    .organizationName("Acme Corp")
    .goal("analyze_kpis")
    .build());

// Generate AI narrative
Map<String, Object> narrative = client.mcp().generateNarrative(McpNarrativeRequest.builder()
    .organizationName("Acme Corp")
    .language("en")
    .build());

Real-time Streaming — client.stream()

Streaming methods return a Stream<SseEvent> that must be closed after use (try-with-resources) to release the HTTP connection.

// Live KPI feed
try (Stream<SseEvent> events = client.stream().kpis()) {
    events.limit(100).forEach(e -> System.out.printf("[%s] %s%n", e.event(), e.data()));
}

// Anomaly monitoring for a specific organization
try (Stream<SseEvent> anomalies = client.stream().anomaliesByOrg("Acme Corp")) {
    anomalies.forEach(e -> log.warn("ANOMALY: {}", e.data()));
}

// Stream a specific KPI
try (Stream<SseEvent> kpi = client.stream().kpiByCode("REVENUE_GROWTH")) {
    kpi.limit(50).forEach(e -> System.out.println(e.data()));
}

// Streaming pipeline
client.stream().createPipeline(CreatePipelineRequest.builder()
    .name("revenue-agg")
    .organizationName("Acme Corp")
    .build());
try (Stream<SseEvent> pipeline = client.stream().streamPipeline("revenue-agg")) {
    pipeline.limit(200).forEach(e -> System.out.println(e.data()));
}

// Real-time report generation
try (Stream<SseEvent> report = client.stream().generateReport(
        GenerateReportStreamRequest.builder()
            .templateName("monthly-financial")
            .organizationName("Acme Corp")
            .build())) {
    report.forEach(e -> System.out.println(e.data()));
}

Organizations — client.organizations()

BrandConfig brand = client.organizations().createBrandConfig(
    CreateBrandConfigRequest.builder()
        .organizationName("Acme Corp")
        .primaryColor("#0056b3")
        .logoUrl("https://cdn.acme.com/logo.svg")
        .build());

client.organizations().updateBrandConfig("Acme Corp",
    UpdateBrandConfigRequest.builder()
        .primaryColor("#003d8c")
        .build());

Error Handling

All API errors surface as FastBiApiException (unchecked):

try {
    Kpi kpi = client.kpis().get("UNKNOWN", "Acme Corp");
} catch (FastBiApiException e) {
    System.out.println("HTTP status: " + e.getStatusCode());
    System.out.println("Body: " + e.getResponseBody());
}

Network errors and serialization problems throw RuntimeException wrapping the root cause.

Examples

All examples read credentials from environment variables:

export FASTBI_BASE_URL=http://localhost:3050/api/v1
export FASTBI_CLIENT_ID=your_client
export FASTBI_SECRET=your_secret
Directory What it covers
examples/kpi-lifecycle/ Full KPI lifecycle: create → read → update → list with filters → history → delete
examples/report-pipeline/ Report run lifecycle: create → stage transitions → review → narrative → export → schedule
examples/streaming/ Concurrent SSE streams: KPI feed, anomaly alerts, aggregation pipeline
examples/mcp-analytics/ MCP orchestration: query routing, full analysis, anomaly detection, narrative
examples/ai-intelligence/ All AI analysis endpoints: customers, financial, KPIs, products, automotive
examples/accounting-workflow/ Accounting templates → fiscal year workflows → compliance calendar
examples/database-connections/ Register connections, execute queries, discover schema, manage saved queries
examples/ml-regression/ Train linear regression → inspect model → single and batch predictions

Thread Safety

FastBiClient is fully thread-safe and should be created once and shared. Token refresh uses a ReentrantLock to prevent concurrent refresh storms.

Roadmap

  • OAuth 2.0 client credentials flow
  • Automatic retry with exponential back-off
  • Request/response logging interceptor hook
  • Typed response records for all endpoints (currently Map<String, Object> where schema is not yet stable)
  • Reactive (Project Reactor / WebFlux) SSE adapter

License

Apache 2.0 — see LICENSE.

About

SDK from FastBI App API with Java 21 and SpringBoot

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages