The Speedy Java Client provides a fluent, type-safe API for interacting with Speedy-enabled backends. It offers a clean, builder-based interface for making CRUD operations and complex queries.
<dependency>
<groupId>com.github.silentsamurai</groupId>
<artifactId>speedy-java-client</artifactId>
<version>3.1.4</version>
</dependency>
import static com.github.silent.samurai.speedy.api.client.SpeedyQuery.*;
// Create a client
RestTemplate restTemplate = new RestTemplate();
SpeedyClient<SpeedyResponse> client = SpeedyClient.restTemplate(restTemplate, "http://localhost:8080");
// Create a new category
SpeedyResponse response = client.create("Category")
.addField("name", "cat-client-1")
.execute();
// Query categories
SpeedyQuery query = SpeedyQuery.from("Category")
.where(condition("name", eq("cat-client-1")))
.build();
SpeedyResponse categories = client.query(query).execute();
import static com.github.silent.samurai.speedy.api.client.SpeedyQuery.*;
@SpringBootTest
@AutoConfigureMockMvc
class CategoryControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
void testCreateCategory() {
SpeedyClient<ResultActions> client = SpeedyClient.mockMvc(mockMvc);
ResultActions result = client.create("Category")
.addField("name", "test-category")
.execute();
result.andExpect(status().isCreated());
}
}
The main client class that provides CRUD operations and query execution.
A fluent query builder for constructing complex database queries with conditions, ordering, pagination, and entity expansions.
The Java client supports both simple and multi-level entity expansions:
// Simple expansion
SpeedyQuery query = SpeedyQuery.from("inventory")
.expand("Product")
.expand("Procurement")
.build();
// Multi-level expansion with dot notation
SpeedyQuery query = SpeedyQuery.from("inventory")
.expand("Product")
.expand("Product.Category")
.expand("Product.Category.Supplier")
.expand("Procurement")
.expand("Procurement.Product")
.build();
// Execute the query
SpeedyResponse response = client.query(query).execute();
For detailed information about multi-level expansions, see Multi-Level Expansions.
When using get() without a primary key, you can apply field selection, pagination, and expansion via URL query
parameters:
Speedy speedy = Speedy.connect("http://localhost:8080");
// Select specific fields
List<Product> products = speedy.get("Product")
.select("id", "name", "description")
.execute()
.list(Product.class);
// Select + pagination + expansion
List<Product> products = speedy.get("Product")
.select("id", "name")
.pageSize(20)
.pageNo(0)
.expand("category")
.execute()
.list(Product.class);
// Count query
SpeedyResult result = speedy.get("Product")
.select("$count")
.execute();
long count = result.raw().get("count").asLong();
These methods produce URL query parameters ($select=id,name&$pageSize=20&...) rather than JSON body fields, matching
the GET Operation API.
All transports guarantee UTF-8 encoding for both request and response:
Content-Type: application/json;charset=UTF-8 on requests with a bodyAccept: application/json;charset=UTF-8 on all requestsMockMvcTransport sets characterEncoding=UTF-8 on the request builderRestTemplateTransport configures StringHttpMessageConverter(StandardCharsets.UTF_8)JdkHttpTransport uses BodyPublishers.ofString(body, StandardCharsets.UTF_8)Response bodies are always decoded as UTF-8.
The Java client supports multiple HTTP client implementations:
| Client | Use Case | Factory Method |
|---|---|---|
| RestTemplate | Production applications | SpeedyClient.restTemplate(restTemplate, baseUrl) |
| MockMvc | Unit/integration testing | SpeedyClient.mockMvc(mockMvc) |
| Custom | Custom implementations | SpeedyClient.from(httpClient) |
import static com.github.silent.samurai.speedy.api.client.SpeedyQuery.*;
import com.fasterxml.jackson.databind.JsonNode;
import com.github.silent.samurai.speedy.api.client.models.SpeedyResponse;
SpeedyResponse response = client.get("users").execute();
JsonNode payload = response.getPayload();
if (payload != null && !payload.isEmpty()) {
// Process data from payload
if (payload.isArray()) {
// Handle array of entities
for (JsonNode user : payload) {
// Process each user
}
} else if (payload.isObject()) {
// Handle single entity
// Process the user object
}
} else {
// Handle empty or null response
log.warn("No data returned from API");
}
RestTemplate for productionMockMvc for testingThe client provides comprehensive error handling:
try{
SpeedyResponse response = client.create("users")
.addField("name", "John Doe")
.addField("email", "john@example.com")
.execute();
}catch(
SpeedyClientException e){
// Handle client-specific errors
log.
error("Client error: {}",e.getMessage());
}catch(
Exception e){
// Handle general errors
log.
error("Unexpected error: {}",e.getMessage());
}