Sure, with openai-java 3.1.2 sdk:
public void runOpenAITest() {
OpenAIClient client = OpenAIOkHttpClient.builder().baseUrl("https://generativelanguage.googleapis.com/v1beta/openai/").apiKey("KEY").build();
ChatCompletionCreateParams.Builder builder = ChatCompletionCreateParams.builder();
builder.model("gemini-2.5-flash");
builder.addMessage(ChatCompletionMessageParam.ofUser(ChatCompletionUserMessageParam.builder().content("hello").build()));
Mono.fromCallable(() -> {
System.out.println("First request...");
return builder.build();
})
.flatMapMany(params -> generateContentStream(client, params))
.collect(ChatCompletionAccumulator::create, ChatCompletionAccumulator::accumulate)
.flatMap(accumulator -> {
ChatCompletion chatCompletion = accumulator.chatCompletion();
chatCompletion.choices().forEach(choice -> {
System.out.println("First reply: " + choice.message().content());
ChatCompletionMessage.Builder assistant = choice.message().toBuilder();
// ***** should set null refusal to json ignored manully
//if (choice.message().refusal().isEmpty()) {
// assistant.refusal(JsonMissing.of());
//}
builder.addMessage(assistant.build());
});
builder.addMessage(ChatCompletionMessageParam.ofUser(ChatCompletionUserMessageParam.builder().content("how are you").build()));
return Mono.just(builder.build());
})
.flatMapMany(params -> {
System.out.println("Second request...");
return generateContentStream(client, params);
})
.collect(ChatCompletionAccumulator::create, ChatCompletionAccumulator::accumulate)
.doOnNext(accumulator -> {
ChatCompletion chatCompletion = accumulator.chatCompletion();
chatCompletion.choices().forEach(choice -> {
System.out.println("Second reply: " + choice.message().content());
});
})
.doOnTerminate(() -> {
System.out.println("All requests processed");
})
.doOnError(error -> {
System.err.println("Error processing: " + error.getMessage());
error.printStackTrace();
})
.subscribe();
}
private static Flux<ChatCompletionChunk> generateContentStream(OpenAIClient client, ChatCompletionCreateParams request) {
System.out.println(request.toString());
return Flux.create(emitter -> {
AsyncStreamResponse<ChatCompletionChunk> streamResponse = client.async().chat().completions().createStreaming(request);
streamResponse.subscribe(new AsyncStreamResponse.Handler<>() {
@Override
public void onNext(ChatCompletionChunk event) {
emitter.next(event);
}
@Override
public void onComplete(@NotNull Optional<Throwable> error) {
if (error.isPresent()) {
emitter.error(error.get());
}
else {
emitter.complete();
}
}
});
});
}
Result without the field handler, as refusal=null in the params:
First request...
ChatCompletionCreateParams{body=Body{messages=[ChatCompletionMessageParam{user=ChatCompletionUserMessageParam{content=Content{text=hello}, role=user, name=, additionalProperties={}}}], model=gemini-2.5-flash, audio=, frequencyPenalty=, functionCall=, functions=, logitBias=, logprobs=, maxCompletionTokens=, maxTokens=, metadata=, modalities=, n=, parallelToolCalls=, prediction=, presencePenalty=, promptCacheKey=, reasoningEffort=, responseFormat=, safetyIdentifier=, seed=, serviceTier=, stop=, store=, streamOptions=, temperature=, toolChoice=, tools=, topLogprobs=, topP=, user=, verbosity=, webSearchOptions=, additionalProperties={}}, additionalHeaders=Headers{map={}}, additionalQueryParams=QueryParams{map={}}}
First reply: Optional[Hello! How can I help you today?]
Second request...
ChatCompletionCreateParams{body=Body{messages=[ChatCompletionMessageParam{user=ChatCompletionUserMessageParam{content=Content{text=hello}, role=user, name=, additionalProperties={}}}, ChatCompletionMessageParam{assistant=ChatCompletionAssistantMessageParam{role=assistant, audio=, content=Content{text=Hello! How can I help you today?}, functionCall=, name=, refusal=null, toolCalls=[], additionalProperties={}}}, ChatCompletionMessageParam{user=ChatCompletionUserMessageParam{content=Content{text=how are you}, role=user, name=, additionalProperties={}}}], model=gemini-2.5-flash, audio=, frequencyPenalty=, functionCall=, functions=, logitBias=, logprobs=, maxCompletionTokens=, maxTokens=, metadata=, modalities=, n=, parallelToolCalls=, prediction=, presencePenalty=, promptCacheKey=, reasoningEffort=, responseFormat=, safetyIdentifier=, seed=, serviceTier=, stop=, store=, streamOptions=, temperature=, toolChoice=, tools=, topLogprobs=, topP=, user=, verbosity=, webSearchOptions=, additionalProperties={}}, additionalHeaders=Headers{map={}}, additionalQueryParams=QueryParams{map={}}}
Error processing: com.openai.errors.BadRequestException: 400: null
Result with the field hander, as refusal= and ignored in the params:
First request...
ChatCompletionCreateParams{body=Body{messages=[ChatCompletionMessageParam{user=ChatCompletionUserMessageParam{content=Content{text=hello}, role=user, name=, additionalProperties={}}}], model=gemini-2.5-flash, audio=, frequencyPenalty=, functionCall=, functions=, logitBias=, logprobs=, maxCompletionTokens=, maxTokens=, metadata=, modalities=, n=, parallelToolCalls=, prediction=, presencePenalty=, promptCacheKey=, reasoningEffort=, responseFormat=, safetyIdentifier=, seed=, serviceTier=, stop=, store=, streamOptions=, temperature=, toolChoice=, tools=, topLogprobs=, topP=, user=, verbosity=, webSearchOptions=, additionalProperties={}}, additionalHeaders=Headers{map={}}, additionalQueryParams=QueryParams{map={}}}
First reply: Optional[Hello! How can I help you today?]
Second request...
ChatCompletionCreateParams{body=Body{messages=[ChatCompletionMessageParam{user=ChatCompletionUserMessageParam{content=Content{text=hello}, role=user, name=, additionalProperties={}}}, ChatCompletionMessageParam{assistant=ChatCompletionAssistantMessageParam{role=assistant, audio=, content=Content{text=Hello! How can I help you today?}, functionCall=, name=, refusal=, toolCalls=[], additionalProperties={}}}, ChatCompletionMessageParam{user=ChatCompletionUserMessageParam{content=Content{text=how are you}, role=user, name=, additionalProperties={}}}], model=gemini-2.5-flash, audio=, frequencyPenalty=, functionCall=, functions=, logitBias=, logprobs=, maxCompletionTokens=, maxTokens=, metadata=, modalities=, n=, parallelToolCalls=, prediction=, presencePenalty=, promptCacheKey=, reasoningEffort=, responseFormat=, safetyIdentifier=, seed=, serviceTier=, stop=, store=, streamOptions=, temperature=, toolChoice=, tools=, topLogprobs=, topP=, user=, verbosity=, webSearchOptions=, additionalProperties={}}, additionalHeaders=Headers{map={}}, additionalQueryParams=QueryParams{map={}}}
Second reply: Optional[As an AI, I don't have feelings or a physical state like humans do, so I can't be "good" or "bad" in the traditional sense.
However, I'm functioning perfectly and ready to assist you! How are you doing today?]
All requests processed