Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Mindee Java Client Library Changelog

## v5.0.0-beta2 - 2026-05-20
### ¡Breaking Changes!
* :recycle: put error parsing in its own package
### Changes
* :sparkles: add model search API


## v5.0.0-beta1 - 2026-05-06
### ¡Breaking Changes!
* :coffin: Remove obsolete/unused products:
Expand Down
4 changes: 2 additions & 2 deletions docs/code_samples/v2_classification.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ public class SimpleMindeeClientV2 {
throws IOException, InterruptedException
{
String apiKey = "MY_API_KEY";
String filePath = "/path/to/the/file.ext";
String modelId = "MY_MODEL_ID";
String filePath = "/path/to/the/file.ext";

// Init a new client
var mindeeClient = new MindeeClient(apiKey);
Expand All @@ -38,6 +38,6 @@ public class SimpleMindeeClientV2 {

// Access the classification result
var result = response.getInference().getResult();
var classification = result.getClassification();
String documentType = result.getClassification().getDocumentType();
}
}
4 changes: 2 additions & 2 deletions docs/code_samples/v2_crop.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ public class SimpleMindeeClientV2 {
throws IOException, InterruptedException
{
String apiKey = "MY_API_KEY";
String filePath = "/path/to/the/file.ext";
String modelId = "MY_MODEL_ID";
String filePath = "/path/to/the/file.ext";

// Init a new client
var mindeeClient = new MindeeClient(apiKey);
Expand All @@ -36,6 +36,6 @@ public class SimpleMindeeClientV2 {
System.out.println(response.getInference().toString());

// Access the crop results
var result = response.getInference().getResult();
var crops = response.getInference().getResult().getCrops();
}
}
2 changes: 1 addition & 1 deletion docs/code_samples/v2_extraction.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ public class SimpleMindeeClientV2 {
throws IOException, InterruptedException
{
String apiKey = "MY_API_KEY";
String filePath = "/path/to/the/file.ext";
String modelId = "MY_MODEL_ID";
String filePath = "/path/to/the/file.ext";

// Init a new client
var mindeeClient = new MindeeClient(apiKey);
Expand Down
2 changes: 1 addition & 1 deletion docs/code_samples/v2_ocr.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,6 @@ public class SimpleMindeeClientV2 {
System.out.println(response.getInference().toString());

// Access the result OCR pages
var result = response.getInference().getResult();
var pages = response.getInference().getResult().getPages();
}
}
4 changes: 2 additions & 2 deletions docs/code_samples/v2_split.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ public class SimpleMindeeClientV2 {
throws IOException, InterruptedException
{
String apiKey = "MY_API_KEY";
String filePath = "/path/to/the/file.ext";
String modelId = "MY_MODEL_ID";
String filePath = "/path/to/the/file.ext";

// Init a new client
var mindeeClient = new MindeeClient(apiKey);
Expand All @@ -36,6 +36,6 @@ public class SimpleMindeeClientV2 {
System.out.println(response.getInference().toString());

// Access the split result
var result = response.getInference().getResult();
var splits = response.getInference().getResult().getSplits();
}
}
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@

<properties>
<!-- MINDEE VERSION GOES HERE -->
<revision>5.0.0-beta1</revision>
<revision>5.0.0-beta2</revision>

<!-- Give special access when running tests -->
<surefire.addOpens>
Expand Down
33 changes: 32 additions & 1 deletion src/main/java/com/mindee/v2/MindeeClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
import com.mindee.v2.http.MindeeHttpApiV2;
import com.mindee.v2.http.MindeeHttpExceptionV2;
import com.mindee.v2.parsing.CommonResponse;
import com.mindee.v2.parsing.ErrorResponse;
import com.mindee.v2.parsing.JobResponse;
import com.mindee.v2.parsing.error.ErrorResponse;
import com.mindee.v2.parsing.search.SearchResponse;
import com.mindee.v2.product.extraction.ExtractionResponse;
import java.io.IOException;

Expand Down Expand Up @@ -172,6 +173,36 @@ public <TResponse extends CommonResponse> TResponse enqueueAndGetResult(
return pollAndFetch(responseClass, job, pollingOptions);
}

/**
* Return all models.
*
* @return an instance of {@link SearchResponse}
*/
public SearchResponse searchModels() {
return searchModels(null, null);
}

/**
* Search for models by name.
*
* @param modelName name of the model to search for
* @return an instance of {@link SearchResponse}
*/
public SearchResponse searchModels(String modelName) {
return searchModels(modelName, null);
}

/**
* Search for models by name and type.
*
* @param modelName name of the model to search for
* @param modelType type of the model to search for
* @return an instance of {@link SearchResponse}
*/
public SearchResponse searchModels(String modelName, String modelType) {
return mindeeApi.reqGetSearchModels(modelName, modelType);
}

/**
* Common logic for polling an asynchronous job for local & url files.
*
Expand Down
13 changes: 11 additions & 2 deletions src/main/java/com/mindee/v2/http/MindeeApiV2.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
import com.mindee.input.URLInputSource;
import com.mindee.v2.clientoptions.BaseParameters;
import com.mindee.v2.parsing.CommonResponse;
import com.mindee.v2.parsing.ErrorResponse;
import com.mindee.v2.parsing.JobResponse;
import com.mindee.v2.parsing.error.ErrorResponse;
import com.mindee.v2.parsing.search.SearchResponse;
import java.io.IOException;

/**
Expand Down Expand Up @@ -48,11 +49,19 @@ public abstract JobResponse reqPostEnqueue(
*
* @param inferenceId ID of the inference to poll.
*/
abstract public <TResponse extends CommonResponse> TResponse reqGetResult(
public abstract <TResponse extends CommonResponse> TResponse reqGetResult(
Class<TResponse> responseClass,
String inferenceId
);

/**
* Retrieves a list of models.
*
* @param modelName search term for model name
* @param modelType search term for model type
*/
public abstract SearchResponse reqGetSearchModels(String modelName, String modelType);

/**
* Creates an "unknown error" response from an HTTP status code.
*/
Expand Down
115 changes: 47 additions & 68 deletions src/main/java/com/mindee/v2/http/MindeeHttpApiV2.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@
import com.mindee.v2.MindeeSettings;
import com.mindee.v2.clientoptions.BaseParameters;
import com.mindee.v2.parsing.CommonResponse;
import com.mindee.v2.parsing.ErrorResponse;
import com.mindee.v2.parsing.JobResponse;
import com.mindee.v2.parsing.error.ErrorResponse;
import com.mindee.v2.parsing.search.SearchResponse;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import lombok.Builder;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
Expand Down Expand Up @@ -82,7 +84,7 @@ public JobResponse reqPostEnqueue(LocalInputSource inputSource, BaseParameters o
inputSource.getFilename()
);
post.setEntity(options.buildHttpBody(builder).build());
return executeEnqueue(post);
return executeAPIRequest(post, JobResponse.class);
}

/**
Expand All @@ -103,33 +105,7 @@ public JobResponse reqPostEnqueue(URLInputSource inputSource, BaseParameters opt
builder.setMode(HttpMultipartMode.EXTENDED);
builder.addTextBody("url", inputSource.getUrl().toString());
post.setEntity(options.buildHttpBody(builder).build());
return executeEnqueue(post);
}

/**
* Executes an enqueue action, common to URL & local inputs.
*
* @param post HTTP Post object.
* @return a valid job response.
*/
private JobResponse executeEnqueue(HttpPost post) {
try (var httpClient = httpClientBuilder.build()) {
return httpClient.execute(post, response -> {
var responseEntity = response.getEntity();
var statusCode = response.getCode();
if (isInvalidStatusCode(statusCode)) {
throw getHttpError(response);
}
try {
var raw = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
return deserializeOrThrow(raw, JobResponse.class, response.getCode());
} finally {
EntityUtils.consumeQuietly(responseEntity);
}
});
} catch (IOException err) {
throw new MindeeException(err.getMessage(), err);
}
return executeAPIRequest(post, JobResponse.class);
}

@Override
Expand All @@ -138,31 +114,10 @@ public JobResponse reqGetJob(String jobId) {
var url = this.mindeeSettings.getBaseUrl() + "/jobs/" + jobId;
var get = new HttpGet(url);

if (this.mindeeSettings.getApiKey().isPresent()) {
get.setHeader(HttpHeaders.AUTHORIZATION, this.mindeeSettings.getApiKey().get());
}
get.setHeader(HttpHeaders.USER_AGENT, getUserAgent());
var noRedirect = RequestConfig.custom().setRedirectsEnabled(false).build();
get.setConfig(noRedirect);

try (var httpClient = httpClientBuilder.build()) {
return httpClient.execute(get, response -> {
var responseEntity = response.getEntity();
var statusCode = response.getCode();
if (isInvalidStatusCode(statusCode)) {
throw getHttpError(response);
}
try {
var raw = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);

return deserializeOrThrow(raw, JobResponse.class, response.getCode());
} finally {
EntityUtils.consumeQuietly(responseEntity);
}
});
} catch (IOException err) {
throw new MindeeException(err.getMessage(), err);
}
return this.executeAPIRequest(get, JobResponse.class);
}

@Override
Expand All @@ -179,25 +134,54 @@ public <TResponse extends CommonResponse> TResponse reqGetResult(
inferenceId
);
var get = new HttpGet(url);
return executeAPIRequest(get, responseClass);
}

@Override
public SearchResponse reqGetSearchModels(String modelName, String modelType) {
URIBuilder url;
try {
url = new URIBuilder(this.mindeeSettings.getBaseUrl() + "/search/models");
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
if (modelName != null) {
url.addParameter("name", modelName);
}
if (modelType != null) {
url.addParameter("type", modelType);
}
var get = new HttpGet(url.toString());
return executeAPIRequest(get, SearchResponse.class);
}

/**
* Executes an enqueue action, common to URL & local inputs.
*
* @param apiRequest HTTP request object.
* @return a valid job response.
*/
private <TResponse extends CommonResponse> TResponse executeAPIRequest(
HttpUriRequestBase apiRequest,
Class<TResponse> responseClass
) {
if (this.mindeeSettings.getApiKey().isPresent()) {
get.setHeader(HttpHeaders.AUTHORIZATION, this.mindeeSettings.getApiKey().get());
apiRequest.setHeader(HttpHeaders.AUTHORIZATION, this.mindeeSettings.getApiKey().get());
}
get.setHeader(HttpHeaders.USER_AGENT, getUserAgent());
apiRequest.setHeader(HttpHeaders.USER_AGENT, getUserAgent());

try (var httpClient = httpClientBuilder.build()) {

return httpClient.execute(get, response -> {
var entity = response.getEntity();
var status = response.getCode();
return httpClient.execute(apiRequest, response -> {
var responseEntity = response.getEntity();
var statusCode = response.getCode();
if (isInvalidStatusCode(statusCode)) {
throw getHttpError(response);
}
try {
if (isInvalidStatusCode(status)) {
throw getHttpError(response);
}
var raw = EntityUtils.toString(entity, StandardCharsets.UTF_8);
return deserializeOrThrow(raw, responseClass, status);
var raw = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
return deserializeOrThrow(raw, responseClass, response.getCode());
} finally {
EntityUtils.consumeQuietly(entity);
EntityUtils.consumeQuietly(responseEntity);
}
});
} catch (IOException err) {
Expand Down Expand Up @@ -235,11 +219,6 @@ private HttpPost buildHttpPost(String url) {
catch (URISyntaxException err) {
return new HttpPost("invalid URI");
}

if (this.mindeeSettings.getApiKey().isPresent()) {
post.setHeader(HttpHeaders.AUTHORIZATION, this.mindeeSettings.getApiKey().get());
}
post.setHeader(HttpHeaders.USER_AGENT, getUserAgent());
return post;
}

Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/mindee/v2/parsing/Job.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.mindee.v1.parsing.common.LocalDateTimeDeserializer;
import com.mindee.v2.parsing.error.ErrorResponse;
import java.time.LocalDateTime;
import java.util.List;
import lombok.AllArgsConstructor;
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/mindee/v2/parsing/JobWebhook.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.mindee.v1.parsing.common.LocalDateTimeDeserializer;
import com.mindee.v2.parsing.error.ErrorResponse;
import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.mindee.v2.parsing;
package com.mindee.v2.parsing.error;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.mindee.v2.parsing;
package com.mindee.v2.parsing.error;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
Expand Down
Loading
Loading