> ## Documentation Index
> Fetch the complete documentation index at: https://doc.lucidworks.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Java SDK Library

export const LwTemplate = ({title = "Key questions to get you started", icon = "sparkles", cta = "Powered by Agent Studio", linkHref = "https://lucidworks.com/demo/?utm_source=docs&utm_medium=referral&utm_campaign=docs_cta_ai"}) => {
  const [isLoaded, setIsLoaded] = useState(false);
  useEffect(() => {
    const timer = setTimeout(() => {
      setIsLoaded(true);
    }, 500);
    return () => clearTimeout(timer);
  }, []);
  return <div className="lw-template-container">
      <Card title={title} icon={icon}>
        {isLoaded && <span dangerouslySetInnerHTML={{
    __html: `<lw-template id="a029c1a9-28be-427e-b0e1-5d918920246a"></lw-template
            >`
  }} />}
        <Link href={linkHref} className="agent-studio-link text-left text-gray-600 gap-2 dark:text-gray-400 text-sm font-medium flex flex-row items-center hover:text-primary dark:hover:text-primary-light group-hover:text-primary group-hover:dark:text-primary-light">Powered by Lucidworks Agent Studio</Link>
      </Card>
    </div>;
};

[localhost link]: http://localhost:3000/docs/5/fusion/dev-portal/query-stage-sdk/java-sdk

[mintlify link]: https://doc.lucidworks.com/docs/5/fusion/dev-portal/query-stage-sdk/java-sdk

[old doc.lw link]: https://doc.lucidworks.com/fusion/5.9/6xhv0g

The Java SDK library contains the classes and interfaces for building new query plugin stages. You’ll find it in the [`query-stage-plugin-sdk` directory](https://github.com/lucidworks/query-stage-sdk/tree/master/query-stage-plugin-sdk).

<LwTemplate />

## Plugins

A plugin is a `.zip` file that contains one or more query stage implementations. The file contains `.jar` files for stage definitions and additional dependencies. It also contains a manifest file that holds the metadata Fusion uses to run the plugin.

For build and deployment instructions, see
**Build and Deploy A Query Stage Plugin**.

<Accordion title="Build and Deploy A Query Stage Plugin">
  This topic explains how to build and deploy a custom query stage plugin that you developed using the Query Stage SDK.

  Fusion also comes with a number of [built-in query stages](/docs/5/fusion/reference/config-ref/pipeline-stages/query-stages/overview) that you can access using the [Query Workbench](/docs/5/fusion/getting-data-out/query-basics/query-workbench).

  ## Prerequisites

  * Clone the [repository](https://github.com/lucidworks/query-stage-sdk).
  * Develop your plugin using the [Query Stage SDK library](/docs/5/fusion/dev-portal/query-stage-sdk/overview).

  ## Build the plugin stage

  From the main folder, run:

  ```bash theme={"dark"}
  ./gradlew -p examples/sample-plugin-stage clean assemblePlugin
  ```

  Substitute the path to your project.

  This creates a plugin `.zip` file (with required manifest file) inside the `build/libs` folder.

  ## Deploy the stage

  You can choose from several different ways to deploy the sample plugin stage:

  * [Upload it to the blob store](#upload-it-to-the-blob-store)
  * [Use gradle](#deploy-it-using-gradle)
  * [Use the REST API](#deploy-it-with-the-rest-api)

  After successful deployment, new stages should be visible in the `Stages` list in the Fusion Query Pipelines UI.

  ### Upload it to the blob store

  1. Navigate to **System > Blobs**.
  2. Click **Add**.
  3. Select **Query Stage Plugin**.
  4. Click **Browse...** and select your plugin file.
  5. Click **Upload**.

  ### Deploy it using gradle

  ```bash theme={"dark"}
  ./gradlew -p examples/sample-plugin-stage deploy -PfusionUser=[user] -PfusionPassword=[password]
  ```

  ### Deploy it with the REST API

  ```bash theme={"dark"}
  curl -u [user]:[password] -X PUT -H "Content-Type:application/zip" --data-binary @sample-plugin-stage-0.0.1.zip https://FUSION_HOST/api/query-stage-plugins
  ```
</Accordion>

Alternatively, it can be assembled by any other build tool as long as the file and directory structure is correct.

## Query Stage

The [`com.lucidworks.querying.api.QueryStage`](https://javadoc.lucidworks.com/query-stage-sdk-javadocs/2.0.0/com/lucidworks/querying/api/QueryStage.html) class is the basic contract for defining a plugin query stage.

A plugin stage class must:

* Implement the [`com.lucidworks.querying.api.QueryStage`](https://javadoc.lucidworks.com/query-stage-sdk-javadocs/2.0.0/com/lucidworks/querying/api/QueryStage.html) interface.
* Be annotated with the [`com.lucidworks.querying.api.Stage`](https://javadoc.lucidworks.com/query-stage-sdk-javadocs/2.0.0/com/lucidworks/querying/api/Stage.html) annotation.

For convenience, the plugin stage can extend
[`com.lucidworks.querying.api.QueryStageBase`](https://javadoc.lucidworks.com/query-stage-sdk-javadocs/2.0.0/com/lucidworks/querying/api/QueryStageBase.html),
which already contains initialization logic and some helpful methods.

Example of a plugin query stage implementation:

```java wrap  theme={"dark"}
@Stage(type = "simple", configClass = SimpleStageConfig.class)
public class SimpleStage extends QueryStageBase<SimpleStageConfig> {

  private static final Logger logger = LoggerFactory.getLogger(SimpleStage.class);

  @Override
  public DslQueryRequestResponse process(DslQueryRequestResponse query, Context context) {
    queryRequestResponse.getDslQueryRequest().getParams().put(config.queryParam(), config.value());
    return queryRequestResponse;
  }
}
```

### Lifecycle

1. Fusion creates a `QueryStage` instance and initializes it.
2. Fusion begins calling the `process` method (see the example above) for each query passing through the query pipeline.

One stage instance can be used by Fusion for processing multiple queries and the `process` method can be called from multiple concurrently-running threads. Additionally, Fusion can initialize and maintain multiple stage instances with the same configuration in separate query service nodes. Therefore, it is important to make sure the plugin stage implementation is thread-safe and processing logic is stateless.

The plugin stage may throw an exception while processing a query. This does *not* cause any side effects; the query will simply not be processed anymore. The whole query pipeline will still be in use and Fusion will continue to call the `process` method for other queries. Any information about thrown exceptions can be found in the logs.

#### Initialization

After creation, each stage object will be initialized using the `init(T config, Fusion fusion)` method. This allows the stage to create any needed internal structure and validate the stage configuration.

Note that initialization occurs immediately after the stage configuration has been saved in Fusion. After this the stage instance can be maintained and re-used by Fusion for extensive periods of time even if no queries pass through the stage. You should be mindful of this fact when making decisions on resource allocations.

#### Query-Response processing

After the stage has been initialized, Fusion will start sending queries to the stage for processing by invoking
`process(DslQueryRequestResponse query, Context context)` on every incoming query.

Note that multiple threads can call the `process` method concurrently, therefore its implementation must be thread-safe.

#### Logging

Query Stage SDK is using the [slf4j logging API](http://www.slf4j.org/). The following example demonstrates how logging can be implemented inside a plugin stage:

```java wrap  theme={"dark"}
public class MyStage extends QueryStageBase<MyStageConfig> {

  private static final Logger logger = LoggerFactory.getLogger(MyStage.class);

  @Override
  public DslQueryRequestResponse process(DslQueryRequestResponse query, Context context) {
    // ......
    logger.info("Processing query '{}'", query);
    // ......
  }
}
```

#### Metrics

Fusion is using [Prometheus and Grafana](/docs/5/fusion/operations/monitoring-and-reporting/prometheus-grafana-loki)
for enhanced metrics collection and querying. Query Stage plugins can add their own custom metrics to the list of
default metrics already generated by the Fusion querying service.

To be able to publish custom metrics the Prometheus client library must be added to the plugin’s dependencies:

```java wrap  theme={"dark"}
provided 'io.prometheus:simpleclient_dropwizard:0.7.0'
```

After that, the Prometheus client can be used to record custom metrics. More information on the Prometheus Java client API can be found in the [Prometheus documentation](https://github.com/prometheus/client_java#instrumenting).

The following code demonstrates how to capture external request time metrics using the Prometheus client API.

```java wrap  theme={"dark"}
public class SampleStage {

  private static final Histogram EXTERNAL_REQUEST_TIME = Histogram.build()
      .help("Time to execute external query request.")
      .name("external_query_request_time")
      .labelNames("request_url")
      .register();

    @Override
    public DslQueryRequestResponse process(DslQueryRequestResponse query, Context context) {
      // ......  
    Histogram.Timer externalQueryTimer = EXTERNAL_REQUEST_TIME
          .labels(requestUrl)
          .startTimer();
      try {
        // perform external request...
      } finally {
        externalQueryTimer.observeDuration();
      }
      // ......
    }
}
```

### Query stage configuration

The [`QueryStageConfig`](https://javadoc.lucidworks.com/query-stage-sdk-javadocs/2.0.0/com/lucidworks/querying/config/QueryStageConfig.html)
defines configuration options specific to a particular query stage instance. These options will be available to the end user via the Fusion UI and API. The plugin config class must extend `com.lucidworks.querying.config.QueryStageConfig` and be annotated with `@RootSchema`.

By adding `@Property` and type annotations to your stage configuration interface methods, you can define metadata and type constraints for your plugin configuration fields. This is very similar to Fusion’s connector configuration schema. For more detailed information on the configuration and schema capabilities, see [Java Connector Development](/docs/fusion-connectors/developers/java-sdk).

Here is an example of a simple stage configuration schema definition:

```java wrap  theme={"dark"}
@RootSchema(
    title = "Simple",
    description = "Simple Query Stage"
)
public interface SimpleStageConfig extends QueryStageConfig {

    @Property(
            title = "Time allowed",
            description = "The amount of time allowed for a search to complete.",
            required = true
    )
    @NumberSchema()
    long timeAllowed();
}
```

## Exposed Fusion APIs

SDK-based plugins are capable of communicating with other Fusion components via the
[`Fusion`](https://javadoc.lucidworks.com/query-stage-sdk-javadocs/2.0.0/com/lucidworks/querying/api/fusion/Fusion.html)
object. This object is passed to the stage during the initialization phase.

### RestCall

The [`RestCall`](https://javadoc.lucidworks.com/query-stage-sdk-javadocs/2.0.0/com/lucidworks/querying/api/fusion/RestCall.html)
API provides access to the [Fusion REST API](/docs/5/fusion/dev-portal/rest-apis).

### Blobs

The [Blobs](https://javadoc.lucidworks.com/query-stage-sdk-javadocs/2.0.0/com/lucidworks/querying/api/fusion/Blobs.html)
API is a specialized API for interaction with the Fusion [Blob Store API](/api-reference/blobs/get-blob-store-service-status)

## Data structures

### DslQueryRequestResponse

[`DslQueryRequestResponse`](https://javadoc.lucidworks.com/query-stage-sdk-javadocs/2.0.0/com/lucidworks/querying/api/DslQueryRequestResponse.html)
is a representation of a query request and response. In Fusion, both the query request and response are treated and tracked as one entity. This is the class that is passed through to the `process` method and may be manipulated to inspect/update the request and/or response.

### DslQueryRequest

[`DslQueryRequest`](https://javadoc.lucidworks.com/query-stage-sdk-javadocs/2.0.0/com/lucidworks/querying/api/DslQueryRequest.html)
is a representation of a query request. You can access this via the `QueryRequestAndResponse` class. It contains information about the query parameters, the headers, as well as the HTTP method called.

### DslQueryResponse

[`DslQueryResponse`](https://javadoc.lucidworks.com/query-stage-sdk-javadocs/2.0.0/com/lucidworks/querying/api/DslQueryResponse.html)
is a representation of a query response. You can access this via the `QueryRequestAndResponse` class. It contains information about the documents, the facets, and any highlighted terms.
