Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
4603422
feat: implement BearerToken OIDC flow
bevzzz Aug 6, 2025
457bd7c
chore: delete old file
bevzzz Aug 6, 2025
9f456aa
feat: throw WeaviateOAuthException when authorization flow fails
bevzzz Aug 6, 2025
42637de
fix: add synchronization on ReuseTokenProvider
bevzzz Aug 6, 2025
f7ad184
feat: reuse token from NimbusTokenProvider
bevzzz Aug 6, 2025
f13083f
fix: never expire token with expiresIn=-1
bevzzz Aug 7, 2025
272aa51
refactor: create rest/grpc transport outside of if-block
bevzzz Aug 14, 2025
330a333
feat: implement ResouceOwnerPassword flow
bevzzz Aug 14, 2025
9a07f77
feat: implement ClientCredentials flow
bevzzz Aug 14, 2025
1f73f0f
chore: rename bearerToken flow to refreshToken internally
bevzzz Aug 14, 2025
78cd310
refactor: drop unused configuration
bevzzz Aug 14, 2025
01e58ea
feat: add user / default scopes
bevzzz Aug 14, 2025
6bd8056
test: finish Bearer Token test case
bevzzz Aug 14, 2025
23d149a
feat: add early expiry to tokens
bevzzz Aug 14, 2025
badbe9e
chore: fix javadoc
bevzzz Aug 14, 2025
eb5607f
chore: fix typo
bevzzz Aug 14, 2025
5fc3ce5
feat: add Authorization to WeaviateClientAsync
bevzzz Aug 14, 2025
ad6ea8b
feat: implement readiness check
bevzzz Aug 14, 2025
897225a
feat: add /meta endpoint
bevzzz Aug 14, 2025
a1615ed
feat: use non-blocking auth interceptor for async client
bevzzz Aug 17, 2025
148cb3f
feat: use non-blocking token provider in the gRPC stub
bevzzz Aug 17, 2025
b519b19
test: target latest Weavite version (1.32.3)
bevzzz Aug 17, 2025
887a64b
refactor: use shared ExecutorService in AsyncTokenProvider.Default
bevzzz Aug 17, 2025
75f8bf6
chore: add javadoc
bevzzz Aug 17, 2025
a898ff9
chore(README): add example of using shaded dependency
bevzzz Aug 18, 2025
3d0df1b
fix: refresh tokens in the background
bevzzz Aug 18, 2025
ba62298
fix: reuse old refresh_token if the new one was not returned
bevzzz Aug 18, 2025
909f1e9
chore: rename Authorization -> Authentication
bevzzz Aug 18, 2025
733bc7d
chore: add comment
bevzzz Aug 20, 2025
06661b9
feat: test that tokens are being refreshed after expiry
bevzzz Aug 21, 2025
f5ef775
refactor: remove redundant variable
bevzzz Aug 22, 2025
01e4017
Merge branch 'v6' into v6-oidc
bevzzz Aug 26, 2025
d72cf26
chore: fix post-merge errors
bevzzz Aug 26, 2025
5a21081
fix: build URL with transport options
bevzzz Aug 26, 2025
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
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ Official Weaviate Java Client.
To start using Weaviate Java Client add the dependency to `pom.xml`:

```xml

<dependency>
<groupId>io.weaviate</groupId>
<artifactId>client6</artifactId>
Expand All @@ -19,9 +18,18 @@ To start using Weaviate Java Client add the dependency to `pom.xml`:

### Uber JAR🫙

If you're building a uber-JAR with something like `maven-assembly-plugin`, use a shaded version with classifier `all`.
If you're building an uber-JAR with something like `maven-assembly-plugin`, use a shaded version with classifier `all`.
This ensures that all dynamically-loaded dependecies of `io.grpc` are resolved correctly.

```xml
<dependency>
<groupId>io.weaviate</groupId>
<artifactId>client6</artifactId>
<version>6.0.0-beta4</version>
<classifier>all</classifier>
</dependency>
```

### SNAPSHOT releases

The latest development version of `client6` is released after every merged pull request. To include it in you project set the version to `6.0.0-SNAPSHOT` and [configure your `<repositories>` section accordingly](https://central.sonatype.org/publish/publish-portal-snapshots/#consuming-snapshot-releases-for-your-project).
Expand Down
10 changes: 0 additions & 10 deletions src/it/java/io/weaviate/containers/Container.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,6 @@ public class Container {
public static final Img2VecNeural IMG2VEC_NEURAL = Img2VecNeural.createDefault();
public static final MinIo MINIO = MinIo.createDefault();

static {
startAll();
}

/** Start all shared Testcontainers. */
// TODO: start lazily!
static void startAll() {
// WEAVIATE.start();
}

/**
* Stop all shared Testcontainers created in {@link #startAll}.
* <p>
Expand Down
120 changes: 97 additions & 23 deletions src/it/java/io/weaviate/containers/Weaviate.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,81 @@
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

import org.testcontainers.weaviate.WeaviateContainer;

import io.weaviate.client6.v1.api.Config;
import io.weaviate.client6.v1.api.WeaviateClient;
import io.weaviate.client6.v1.internal.ObjectBuilder;

public class Weaviate extends WeaviateContainer {
private WeaviateClient clientInstance;

public static final String VERSION = "1.29.1";
public static final String VERSION = "1.32.3";
public static final String DOCKER_IMAGE = "semitechnologies/weaviate";

private volatile SharedClient clientInstance;

public WeaviateClient getClient() {
return getClient(ObjectBuilder.identity());
}

/**
* Get a client for the current Weaviate container.
* As we aren't running tests in parallel at the moment,
* this is not made thread-safe.
* Create a new instance of WeaviateClient connected to this container if none
* exist. Get an existing client otherwise.
*
* The lifetime of this client is tied to that of its container, which means
* that you do not need to {@code close} it manually. It will only truly close
* after the parent Testcontainer is stopped.
*/
public WeaviateClient getClient() {
// FIXME: control from containers?
public WeaviateClient getClient(Function<Config.Custom, ObjectBuilder<Config>> fn) {
if (!isRunning()) {
start();
}
if (clientInstance == null) {
try {
clientInstance = WeaviateClient.local(
if (clientInstance != null) {
return clientInstance;
}

synchronized (this) {
if (clientInstance == null) {
var host = getHost();
var customFn = ObjectBuilder.partial(fn,
conn -> conn
.host(getHost())
.scheme("http")
.httpHost(host)
.grpcHost(host)
.httpPort(getMappedPort(8080))
.grpcPort(getMappedPort(50051)));
} catch (Exception e) {
throw new RuntimeException("create WeaviateClient for Weaviate container", e);
var config = customFn.apply(new Config.Custom()).build();
try {
clientInstance = new SharedClient(config, this);
} catch (Exception e) {
throw new RuntimeException("create WeaviateClient for Weaviate container", e);
}
}
}
return clientInstance;
}

/**
* Create a new instance of WeaviateClient connected to this container.
* Prefer using {@link #getClient} unless your test needs the initialization
* steps to run, e.g. OIDC authorization grant exchange.
*/
public WeaviateClient getNewClient(Function<Config.Custom, ObjectBuilder<Config>> fn) {
if (!isRunning()) {
start();
}
var host = getHost();
var customFn = ObjectBuilder.partial(fn,
conn -> conn
.scheme("http")
.httpHost(host)
.grpcHost(host)
.httpPort(getMappedPort(8080))
.grpcPort(getMappedPort(50051)));
return WeaviateClient.custom(customFn);
}

public static Weaviate createDefault() {
return new Builder().build();
}
Expand Down Expand Up @@ -99,20 +139,32 @@ public Builder withOffloadS3(String accessKey, String secretKey) {
}

public Builder enableTelemetry(boolean enable) {
telemetry = enable;
environment.put("DISABLE_TELEMETRY", Boolean.toString(!enable));
return this;
}

public Builder enableAnonymousAccess(boolean enable) {
environment.put("AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED", Boolean.toString(enable));
return this;
}

public Builder withOIDC(String clientId, String issuer, String usernameClaim, String groupsClaim) {
enableAnonymousAccess(false);
environment.put("AUTHENTICATION_OIDC_ENABLED", "true");
environment.put("AUTHENTICATION_OIDC_CLIENT_ID", clientId);
environment.put("AUTHENTICATION_OIDC_ISSUER", issuer);
environment.put("AUTHENTICATION_OIDC_USERNAME_CLAIM", usernameClaim);
environment.put("AUTHENTICATION_OIDC_GROUPS_CLAIM", groupsClaim);
return this;
}

public Weaviate build() {
var c = new Weaviate(DOCKER_IMAGE + ":" + versionTag);

if (!enableModules.isEmpty()) {
c.withEnv("ENABLE_API_BASED_MODULES", "'true'");
c.withEnv("ENABLE_API_BASED_MODULES", Boolean.TRUE.toString());
c.withEnv("ENABLE_MODULES", String.join(",", enableModules));
}
if (!telemetry) {
c.withEnv("DISABLE_TELEMETRY", "true");
}

environment.forEach((name, value) -> c.withEnv(name, value));
c.withCreateContainerCmdModifier(cmd -> cmd.withHostName("weaviate"));
Expand All @@ -134,10 +186,32 @@ public void stop() {
if (clientInstance == null) {
return;
}
try {
clientInstance.close();
} catch (IOException e) {
// TODO: log error
synchronized (this) {
try {
clientInstance.close(this);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

/** SharedClient's lifetime is tied to that of it's parent container. */
private class SharedClient extends WeaviateClient {
private final Weaviate parent;

private SharedClient(Config config, Weaviate parent) {
super(config);
this.parent = parent;
}

private void close(Weaviate caller) throws Exception {
if (caller == parent) {
super.close();
}
}

@Override
public void close() throws IOException {
}
}
}
Loading