Open steven-barnes opened 4 days ago
Indeed, Kill Bill doesn't return the body upon creation (https://docs.killbill.io/latest/quick_start_with_kb_api#_step_3_create_an_account), but you can ask the client to fetch it automatically using requestOptions.withFollowLocation(true)
: https://github.com/killbill/killbill-client-java/blob/910bcdc58bbf6be08f4b18c5e3bb826837bdcef9/src/main/java/org/killbill/billing/client/KillBillHttpClient.java#L336
IIRC we could never really tell Swagger about this behaviour.
I have tried that, and still get an IOException:
RequestOptions.builder
.withCreatedBy("CS2")
.withFollowLocation(Boolean.TRUE)
.build()
Looking at the code for createAccount
, it seems to be setting followLocation
to TRUE by default.
Are you following https://docs.killbill.io/latest/java_client ?
If so, could you share a Main
class that reproduces the issue on a vanilla installation? The Java client is used pervasively throughout our test suite, and I don't know of any regression.
I am using the latest version in Maven Central, 1.3.6. I have coded a test in Java, and still get an IOException:
package org.example;
import org.killbill.billing.catalog.api.Currency;
import org.killbill.billing.client.*;
import org.killbill.billing.client.api.gen.*;
import org.killbill.billing.client.model.gen.Account;
public class Main {
static KillBillHttpClient client = new KillBillHttpClient(REDACTED);
static AccountApi accountApi = new AccountApi(client);
public static void main(String[] args) {
var requestOptions = RequestOptions.builder()
.withCreatedBy("CS2")
.withFollowLocation(Boolean.TRUE)
.build();
var body = new Account();
body.setName("test");
body.setCurrency(Currency.USD);
body.setExternalKey("xyzzy2");
body.setEmail("test@comcast.com");
try {
var result = accountApi.createAccount(body, requestOptions);
System.out.println(result);
} catch (KillBillClientException e) {
e.printStackTrace();
}
}
}
Unable to reproduce.
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<name>my-app</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>11</maven.compiler.release>
</properties>
<dependencies>
<dependency>
<groupId>org.kill-bill.billing</groupId>
<artifactId>killbill-client-java</artifactId>
<version>1.3.6</version>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to
parent pom) -->
<plugins>
<!-- clean lifecycle, see
https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.4.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see
https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.1</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.3.0</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>3.1.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>3.1.2</version>
</plugin>
<!-- site lifecycle, see
https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.12.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.6.1</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.mycompany.app.App</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
App.java:
package com.mycompany.app;
import org.killbill.billing.catalog.api.Currency;
import org.killbill.billing.client.KillBillClientException;
import org.killbill.billing.client.*;
import org.killbill.billing.client.api.gen.*;
import org.killbill.billing.client.model.gen.Account;
public class App {
public static void main(String[] args) {
String username = "admin";
String password = "password";
String apiKey = "bob";
String apiSecret = "lazar";
String serverHost = "localhost";
int serverPort = 8080;
String kbServerUrl = String.format("http://%s:%d", serverHost, serverPort);
KillBillHttpClient killBillHttpClient = new KillBillHttpClient(kbServerUrl, username, password, apiKey,
apiSecret);
AccountApi accountApi = new AccountApi(killBillHttpClient);
var requestOptions = RequestOptions.builder()
.withCreatedBy("CS2")
.withFollowLocation(Boolean.TRUE)
.build();
var body = new Account();
body.setName("test");
body.setCurrency(Currency.USD);
body.setExternalKey("xyzzy");
body.setEmail("test@comcast.com");
try {
var result = accountApi.createAccount(body, requestOptions);
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Execution:
$ java -jar target/my-app-1.0-SNAPSHOT-jar-with-dependencies.jar
SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details.
class Account {
org.killbill.billing.client.model.gen.Account@fc5e4c1c
accountId: 5dbaf858-5447-4262-8418-ccae0e26ca31
name: test
firstNameLength: null
externalKey: xyzzy
email: test@comcast.com
billCycleDayLocal: 0
currency: USD
parentAccountId: null
isPaymentDelegatedToParent: false
paymentMethodId: null
referenceTime: 2024-11-19T08:14:40.000Z
timeZone: UTC
address1: null
address2: null
postalCode: null
company: null
city: null
state: null
country: null
locale: null
phone: null
notes: null
isMigrated: null
accountBalance: null
accountCBA: null
auditLogs: []
}
$ java -jar target/my-app-1.0-SNAPSHOT-jar-with-dependencies.jar
SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See https://www.slf4j.org/codes.html#noProviders for further details.
org.killbill.billing.client.KillBillClientException: Account already exists for key xyzzy
at org.killbill.billing.client.KillBillHttpClient.throwExceptionOnResponseError(KillBillHttpClient.java:390)
at org.killbill.billing.client.KillBillHttpClient.doPrepareRequestInternal(KillBillHttpClient.java:349)
at org.killbill.billing.client.KillBillHttpClient.doPrepareRequest(KillBillHttpClient.java:296)
at org.killbill.billing.client.KillBillHttpClient.doPost(KillBillHttpClient.java:210)
at org.killbill.billing.client.KillBillHttpClient.doPost(KillBillHttpClient.java:205)
at org.killbill.billing.client.api.gen.AccountApi.createAccount(AccountApi.java:176)
at com.mycompany.app.App.main(App.java:34)
Java version:
$ java -version
openjdk version "11.0.14.1" 2022-02-08 LTS
OpenJDK Runtime Environment Microsoft-31205 (build 11.0.14.1+1-LTS)
OpenJDK 64-Bit Server VM Microsoft-31205 (build 11.0.14.1+1-LTS, mixed mode)
Using the debugger, I can see that the location URL is using http, the request to killbill is using https:
static KillBillHttpClient client = new KillBillHttpClient(
"https://killbill.dev.commerce.comcast.com",
http://killbill.dev.commerce.comcast.com:80/1.0/kb/accounts/16c15fcb-f461-4ae0-baff-ec114883496a
We are self-hosting KB in AWS, and I am testing from my laptop.
This results in an IOException, as there is no response body. Running the code again results in a 409 exception,
Account already exists for key 89f20977-f937-4bd7-82f9-ac4ef07b9999
, indicating the account was successful created.When creating similar accounts in the swagger page, I see the response code is 201, but the server does not return a body. The swagger page suggests that an Account object will be returned. This conflicts with the information in the docs, which says that the endpoint will return a URL in the
location
header.