diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/ApiClient.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/ApiClient.java index 22df9ed64..d24e7a9fc 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/ApiClient.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/ApiClient.java @@ -12,10 +12,8 @@ import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import java.nio.charset.StandardCharsets; import java.util.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -187,12 +185,10 @@ private Request prepareBaseRequest(String method, String path, I in) return new Request(method, path); } else if (InputStream.class.isAssignableFrom(in.getClass())) { InputStream body = (InputStream) in; - String debugBody = ""; - return new Request(method, path, body, debugBody); + return new Request(method, path, body); } else { - String debugBody = serialize(in); - InputStream body = new ByteArrayInputStream(debugBody.getBytes(StandardCharsets.UTF_8)); - return new Request(method, path, body, debugBody); + String body = serialize(in); + return new Request(method, path, body); } } @@ -303,11 +299,15 @@ private String makeLogRecord(Request in, Response out) { in.getHeaders() .forEach((header, value) -> sb.append(String.format("\n * %s: %s", header, value))); } - String requestBody = in.getDebugBody(); - if (requestBody != null && !requestBody.isEmpty()) { - for (String line : bodyLogger.redactedDump(requestBody).split("\n")) { - sb.append("\n> "); - sb.append(line); + if (in.isBodyStreaming()) { + sb.append("\n> (streamed body)"); + } else { + String requestBody = in.getBodyString(); + if (requestBody != null && !requestBody.isEmpty()) { + for (String line : bodyLogger.redactedDump(requestBody).split("\n")) { + sb.append("\n> "); + sb.append(line); + } } } sb.append("\n< "); diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/SimpleHttpServer.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/SimpleHttpServer.java deleted file mode 100644 index d6091ae22..000000000 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/SimpleHttpServer.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.databricks.sdk.core; - -import java.io.*; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.URLDecoder; -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Simplistic and short-lived HTTP server intended to handle one or two requests before shutting - * down. Not intended to serve traffic to the Internet. - */ -class SimpleHttpServer implements Runnable { - - private final ServerSocket server; - private final Handler handler; - private volatile boolean running; - private Thread thread; - - public interface Handler { - void accept(BufferedReader in, PrintWriter out) throws IOException; - } - - public SimpleHttpServer(Handler handler) throws IOException { - this(0, handler); - } - - public SimpleHttpServer(int port, Handler handler) throws IOException { - this.handler = handler; - server = new ServerSocket(port); - } - - public String getUrl() { - return String.format("http://localhost:%d", server.getLocalPort()); - } - - public void accept() throws IOException { - Socket clientSocket = server.accept(); - BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); - PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); - handler.accept(in, out); - out.flush(); - out.close(); - } - - public void start() throws InterruptedException { - running = true; - thread = new Thread(this); - thread.setDaemon(true); - thread.setName(String.format("SimpleHttpServer<%s>", getUrl())); - thread.start(); - } - - public synchronized void stop() { - running = false; - thread.interrupt(); - } - - @Override - public void run() { - while (running) { - try { - accept(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - } - - public static Map query(String line) { - final String regex = "(\\\\?|&)(\\w+)=(.*?)(?:&|\\s|$)"; - final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE); - final Matcher matcher = pattern.matcher(line); - Map query = new HashMap<>(); - while (matcher.find()) { - try { - String raw = matcher.group(3); - String decoded = URLDecoder.decode(raw, "UTF-8"); - query.put(matcher.group(2), decoded); - } catch (UnsupportedEncodingException e) { - // noop - } - } - return query; - } - - public static void main(String[] args) throws IOException { - SimpleHttpServer srv = - new SimpleHttpServer( - 8001, - (in, out) -> { - String firstLine = in.readLine(); - Map query = query(firstLine); - out.println("HTTP/1.1 200 OK"); - out.println("Connection: close"); - out.println("Content-Type: text/plain"); - out.println(); - - out.println(firstLine); - }); - System.out.println(srv.getUrl()); - srv.running = true; - srv.run(); - } -} diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/commons/CommonsHttpClient.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/commons/CommonsHttpClient.java index 22c333e92..4595810bc 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/commons/CommonsHttpClient.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/commons/CommonsHttpClient.java @@ -21,11 +21,15 @@ import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.*; import org.apache.http.entity.InputStreamEntity; +import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class CommonsHttpClient implements HttpClient { + private static final Logger LOG = LoggerFactory.getLogger(CommonsHttpClient.class); private final PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(); private final CloseableHttpClient hc; @@ -117,18 +121,26 @@ private HttpUriRequest transformRequest(Request in) { case Request.DELETE: return new HttpDelete(in.getUri()); case Request.POST: - return withEntity(new HttpPost(in.getUri()), in.getBody()); + return withEntity(new HttpPost(in.getUri()), in); case Request.PUT: - return withEntity(new HttpPut(in.getUri()), in.getBody()); + return withEntity(new HttpPut(in.getUri()), in); case Request.PATCH: - return withEntity(new HttpPatch(in.getUri()), in.getBody()); + return withEntity(new HttpPatch(in.getUri()), in); default: throw new IllegalArgumentException("Unknown method: " + in.getMethod()); } } - private HttpRequestBase withEntity(HttpEntityEnclosingRequestBase request, InputStream body) { - request.setEntity(new InputStreamEntity(body)); + private HttpRequestBase withEntity(HttpEntityEnclosingRequestBase request, Request in) { + if (in.isBodyString()) { + request.setEntity(new StringEntity(in.getBodyString(), StandardCharsets.UTF_8)); + } else if (in.isBodyStreaming()) { + request.setEntity(new InputStreamEntity(in.getBodyStream())); + } else { + LOG.warn( + "withEntity called with a request with no body, so no request entity will be set. URI: {}", + in.getUri()); + } return request; } } diff --git a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/http/Request.java b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/http/Request.java index a43096b6f..351d246ef 100644 --- a/databricks-sdk-java/src/main/java/com/databricks/sdk/core/http/Request.java +++ b/databricks-sdk-java/src/main/java/com/databricks/sdk/core/http/Request.java @@ -1,7 +1,6 @@ package com.databricks.sdk.core.http; import com.databricks.sdk.core.DatabricksException; -import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URI; @@ -19,26 +18,50 @@ public class Request { private String url; private final Map headers = new HashMap<>(); private final Map> query = new TreeMap<>(); - private final InputStream body; - private final String debugBody; + /** + * The body of the request for requests with streaming bodies. At most one of {@link #bodyStream} + * and {@link #bodyString} can be non-null. + */ + private final InputStream bodyStream; + /** + * The body of the request for requests with string bodies. At most one of {@link #bodyStream} and + * {@link #bodyString} can be non-null. + */ + private final String bodyString; + /** + * Whether the body of the request is a streaming body. At most one of {@link #isBodyStreaming} + * and {@link #isBodyString} can be true. + */ + private final boolean isBodyStreaming; + /** + * Whether the body of the request is a string body. At most one of {@link #isBodyStreaming} and + * {@link #isBodyString} can be true. + */ + private final boolean isBodyString; public Request(String method, String url) { - this(method, url, (String) null); + this(method, url, null, null); } - public Request(String method, String url, String body) { - this.method = method; - this.url = url; - this.body = - body != null ? new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8)) : null; - this.debugBody = body; + public Request(String method, String url, String bodyString) { + this(method, url, null, bodyString); } - public Request(String method, String url, InputStream body, String debugBody) { + public Request(String method, String url, InputStream bodyStream) { + this(method, url, bodyStream, null); + } + + private Request(String method, String url, InputStream bodyStream, String bodyString) { + if (bodyStream != null && bodyString != null) { + throw new IllegalArgumentException( + "At most one of bodyStream and bodyString can be non-null"); + } this.method = method; this.url = url; - this.body = body; - this.debugBody = debugBody; + this.bodyStream = bodyStream; + this.bodyString = bodyString; + this.isBodyStreaming = bodyStream != null; + this.isBodyString = bodyString != null; } public Request withHeaders(Map headers) { @@ -135,12 +158,20 @@ public Map> getQuery() { return query; } - public InputStream getBody() { - return body; + public InputStream getBodyStream() { + return bodyStream; + } + + public String getBodyString() { + return bodyString; + } + + public boolean isBodyStreaming() { + return isBodyStreaming; } - public String getDebugBody() { - return debugBody; + public boolean isBodyString() { + return isBodyString; } @Override @@ -151,15 +182,15 @@ public boolean equals(Object o) { return method.equals(request.method) && url.equals(request.url) && Objects.equals(query, request.query) - && Objects.equals(body, request.body); + && Objects.equals(bodyStream, request.bodyStream); } @Override public int hashCode() { - // Note: this is not safe for production, as debugBody will be the same for different requests + // Note: this is not safe for production, as bodyString will be null for different requests // using InputStream. // It is currently only used in tests. - return Objects.hash(method, url, query, debugBody); + return Objects.hash(method, url, query, bodyString); } @Override diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/FixtureServer.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/FixtureServer.java index 432bff74e..363fa10fc 100644 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/FixtureServer.java +++ b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/FixtureServer.java @@ -2,52 +2,218 @@ import static org.junit.jupiter.api.Assertions.fail; -import java.io.Closeable; -import java.io.IOException; -import java.util.HashMap; +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import java.io.*; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import org.apache.commons.io.IOUtils; +import org.opentest4j.AssertionFailedError; public class FixtureServer implements Closeable { - private final SimpleHttpServer server; - private final Map fixtures = new HashMap<>(); + public interface Validation { + void validate(HttpExchange exchange) throws IOException; + } - public FixtureServer() throws IOException { - server = - new SimpleHttpServer( - (in, out) -> { - String line = in.readLine(); - String[] split = line.split("\\s+"); - - String key = String.format("%s %s", split[0], split[1]); - String response = fixtures.get(key); - if (response == null) { - fail(String.format("Cannot find %s fixture", key)); + public static class FixtureMapping { + public static class Builder { + private ArrayList validations = new ArrayList<>(); + private String response; + + public Builder validateMethod(String method) { + this.validations.add( + (exchange) -> { + if (!exchange.getRequestMethod().equals(method)) { + fail("Expected method " + method + " but got " + exchange.getRequestMethod()); + } + }); + return this; + } + + public Builder validatePath(String path) { + this.validations.add( + (exchange) -> { + if (!exchange.getRequestURI().toString().equals(path)) { + fail("Expected path " + path + " but got " + exchange.getRequestURI().getPath()); } + }); + return this; + } + + public Builder validateHeadersPresent(Map> headers) { + this.validations.add( + (exchange) -> { + for (Map.Entry> entry : headers.entrySet()) { + String key = entry.getKey(); + List values = entry.getValue(); + for (String value : values) { + List actualValues = exchange.getRequestHeaders().get(key); + if (actualValues == null) { + fail( + "Expected header " + + key + + " with value " + + value + + " but got no header with that key"); + } + if (!actualValues.contains(value)) { + fail( + "Expected header " + + key + + " with value " + + value + + " but got " + + exchange.getRequestHeaders().get(key)); + } + } + } + }); + return this; + } - out.println("HTTP/1.1 200 OK"); - out.println("Connection: close"); - out.println("Content-Type: text/plain"); - out.println(); - out.println(response); + public Builder validateHeadersAbsent(List headers) { + this.validations.add( + (exchange) -> { + for (String header : headers) { + if (exchange.getRequestHeaders().containsKey(header)) { + fail("Expected header " + header + " to be absent but it was present"); + } + } }); - try { - server.start(); - } catch (InterruptedException e) { - throw new RuntimeException(e); + return this; + } + + public Builder validateBody(String body) { + this.validations.add( + (exchange) -> { + String bodyString = + IOUtils.toString(exchange.getRequestBody(), StandardCharsets.UTF_8); + if (!bodyString.equals(body)) { + fail("Expected body " + body + " but got " + bodyString); + } + }); + return this; + } + + public Builder withResponse(String response) { + this.response = response; + return this; + } + + public FixtureMapping build() { + Validation validation = + (exchange) -> { + for (Validation v : validations) { + v.validate(exchange); + } + }; + return new FixtureMapping(validation, response); + } + } + + private final Validation validation; + private final String response; + + FixtureMapping(Validation validation, String response) { + this.validation = validation; + this.response = response; + } + + Validation getValidation() { + return validation; + } + + String getResponse() { + return response; + } + } + + private final HttpServer server; + private final List fixtures = new ArrayList<>(); + + public FixtureServer() throws IOException { + HttpHandler handler = new FixtureHandler(); + server = HttpServer.create(new InetSocketAddress("localhost", 0), 0); + server.createContext("/", handler); + server.start(); + } + + class FixtureHandler implements HttpHandler { + @Override + public void handle(HttpExchange exchange) throws IOException { + try { + handlerInner(exchange); + } catch (Exception e) { + respondInternalServerError(exchange, e.getMessage()); + } } + + private void handlerInner(HttpExchange exchange) throws IOException { + if (fixtures.isEmpty()) { + respondInternalServerError(exchange, "No fixtures defined"); + return; + } + + FixtureMapping response = fixtures.remove(0); + + try { + response.getValidation().validate(exchange); + } catch (AssertionFailedError e) { + respondBadRequest(exchange, e.getMessage()); + return; + } + + respondSuccess(exchange, response.getResponse()); + } + + private void respond(HttpExchange exchange, int statusCode, String body) throws IOException { + Headers headers = exchange.getResponseHeaders(); + headers.add("Connection", "close"); + headers.add("Content-Type", "text/plain"); + exchange.sendResponseHeaders(statusCode, body.length()); + exchange.getResponseBody().write(body.getBytes()); + exchange.close(); + } + + private void respondBadRequest(HttpExchange exchange, String body) throws IOException { + respond(exchange, 400, body); + } + + private void respondInternalServerError(HttpExchange exchange, String body) throws IOException { + respond(exchange, 500, body); + } + + private void respondSuccess(HttpExchange exchange, String body) throws IOException { + respond(exchange, 200, body); + } + } + + public FixtureServer with(String method, String path, String response) { + FixtureMapping fixture = + new FixtureMapping.Builder() + .validateMethod(method) + .validatePath(path) + .withResponse(response) + .build(); + return with(fixture); } - public FixtureServer with(String request, String body) { - fixtures.put(request, body); + public FixtureServer with(FixtureMapping fixture) { + fixtures.add(fixture); return this; } @Override - public void close() throws IOException { - server.stop(); + public void close() { + server.stop(0); } public String getUrl() { - return server.getUrl(); + return "http://" + server.getAddress().getHostName() + ":" + server.getAddress().getPort(); } } diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/SimpleHttpServerTest.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/SimpleHttpServerTest.java deleted file mode 100644 index b57e2850b..000000000 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/SimpleHttpServerTest.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.databricks.sdk.core; - -import static com.databricks.sdk.core.SimpleHttpServer.query; -import static org.junit.jupiter.api.Assertions.*; - -import com.databricks.sdk.WorkspaceClient; -import com.databricks.sdk.core.commons.CommonsHttpClient; -import com.databricks.sdk.service.compute.ListNodeTypesResponse; -import com.databricks.sdk.service.compute.NodeType; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; - -class SimpleHttpServerTest { - - @Test - void sample() throws IOException { - try (FixtureServer fixtures = new FixtureServer()) { - fixtures.with( - "GET /api/2.0/clusters/list-node-types", - "{\"node_types\": [{\"category\":\"testCategory\"}]}"); - - DatabricksConfig config = - new DatabricksConfig() - .setHost(fixtures.getUrl()) - .setToken("testToken") - .setHttpClient(new CommonsHttpClient(30)); - DatabricksConfig mockConfig = Mockito.spy(config); - Mockito.doReturn(mockConfig).when(mockConfig).resolve(); - - WorkspaceClient workspace = new WorkspaceClient(mockConfig); - ListNodeTypesResponse nodeTypes = workspace.clusters().listNodeTypes(); - - assertEquals(1, nodeTypes.getNodeTypes().size()); - assertTrue(nodeTypes.getNodeTypes().contains(new NodeType().setCategory("testCategory"))); - } - } - - @Test - public void testQuery() { - String line = "?param1=value1¶m2=value2¶m3=value3"; - - Map expectedQuery = new HashMap<>(); - expectedQuery.put("param1", "value1"); - expectedQuery.put("param2", "value2"); - expectedQuery.put("param3", "value3"); - - Map actualQuery = query(line); - - assertEquals(expectedQuery.size(), actualQuery.size()); - assertTrue(expectedQuery.entrySet().containsAll(actualQuery.entrySet())); - } -} diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/commons/CommonsHttpClientTest.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/commons/CommonsHttpClientTest.java index 4e7cd79a8..42279bffa 100644 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/commons/CommonsHttpClientTest.java +++ b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/commons/CommonsHttpClientTest.java @@ -7,16 +7,61 @@ import com.databricks.sdk.core.http.Request; import com.databricks.sdk.core.http.Response; import java.io.IOException; +import java.util.*; +import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; class CommonsHttpClientTest { @Test public void itWorks() throws IOException { - try (FixtureServer fixtures = new FixtureServer().with("GET /foo?x=y", "bar")) { + try (FixtureServer fixtures = new FixtureServer().with("GET", "/foo?x=y", "bar")) { HttpClient httpClient = new CommonsHttpClient(30); Request in = new Request("GET", fixtures.getUrl() + "/foo").withQueryParam("x", "y"); Response out = httpClient.execute(in); assertEquals("bar", out.getDebugBody().trim()); } } + + // Test that requests with a string body are sent with no Transfer-Encoding header and with a + // Content-Length header. + @Test + public void testStringBody() throws IOException { + FixtureServer.FixtureMapping fixture = + new FixtureServer.FixtureMapping.Builder() + .validatePath("/foo") + .validateMethod("POST") + .validateHeadersPresent( + Collections.singletonMap("Content-Length", Collections.singletonList("3"))) + .validateHeadersAbsent(Collections.singletonList("Transfer-Encoding")) + .withResponse("quux") + .build(); + try (FixtureServer fixtures = new FixtureServer().with(fixture)) { + HttpClient httpClient = new CommonsHttpClient(30); + Request in = new Request("POST", fixtures.getUrl() + "/foo", "bar"); + Response out = httpClient.execute(in); + assertEquals("quux", out.getDebugBody().trim()); + } + } + + // Test that requests with an InputStream body are sent with a Transfer-Encoding header and + // without a Content-Length header. + @Test + public void testInputStreamBody() throws IOException { + FixtureServer.FixtureMapping fixture = + new FixtureServer.FixtureMapping.Builder() + .validatePath("/foo") + .validateMethod("POST") + .validateHeadersPresent( + Collections.singletonMap("Transfer-Encoding", Collections.singletonList("chunked"))) + .validateHeadersAbsent(Collections.singletonList("Content-Length")) + .withResponse("quux") + .build(); + try (FixtureServer fixtures = new FixtureServer().with(fixture)) { + HttpClient httpClient = new CommonsHttpClient(30); + Request in = + new Request("POST", fixtures.getUrl() + "/foo", IOUtils.toInputStream("bar", "UTF-8")); + Response out = httpClient.execute(in); + assertEquals("quux", out.getDebugBody().trim()); + } + } } diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/http/FormRequestTest.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/http/FormRequestTest.java index 4545c06eb..15a9ceea2 100644 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/http/FormRequestTest.java +++ b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/http/FormRequestTest.java @@ -14,7 +14,7 @@ public void itWorks() { data.put("new", "foo"); FormRequest request = new FormRequest("/foo", data); assertEquals("POST", request.getMethod()); - assertEquals("foo=bar&new=foo", request.getDebugBody()); + assertEquals("foo=bar&new=foo", request.getBodyString()); assertEquals("application/x-www-form-urlencoded", request.getHeaders().get("Content-Type")); } } diff --git a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/ExternalBrowserCredentialsProviderTest.java b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/ExternalBrowserCredentialsProviderTest.java index ed5874533..08f3b7284 100644 --- a/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/ExternalBrowserCredentialsProviderTest.java +++ b/databricks-sdk-java/src/test/java/com/databricks/sdk/core/oauth/ExternalBrowserCredentialsProviderTest.java @@ -20,10 +20,14 @@ public class ExternalBrowserCredentialsProviderTest { @Test void clientAndConsentTest() throws IOException { + FixtureServer.FixtureMapping fixture = + new FixtureServer.FixtureMapping.Builder() + .validateMethod("GET") + .validatePath("/oidc/.well-known/oauth-authorization-server") + .withResponse("{\"token_endpoint\": \"tokenEndPointFromServer\"}") + .build(); try (FixtureServer fixtures = new FixtureServer()) { - fixtures.with( - "GET /oidc/.well-known/oauth-authorization-server", - "{\"token_endpoint\": \"tokenEndPointFromServer\"}"); + fixtures.with(fixture).with(fixture); DatabricksConfig config = new DatabricksConfig() .setAuthType("external-browser") diff --git a/examples/cli-auth-demo/pom.xml b/examples/cli-auth-demo/pom.xml index 724e32132..8f0881bff 100644 --- a/examples/cli-auth-demo/pom.xml +++ b/examples/cli-auth-demo/pom.xml @@ -22,9 +22,9 @@ 0.0.1 - org.apache.logging.log4j - log4j-slf4j2-impl - 2.20.0 + org.slf4j + slf4j-reload4j + 2.0.7 diff --git a/examples/cli-auth-demo/src/main/resources/log4j.properties b/examples/cli-auth-demo/src/main/resources/log4j.properties new file mode 100644 index 000000000..bac6164bd --- /dev/null +++ b/examples/cli-auth-demo/src/main/resources/log4j.properties @@ -0,0 +1,13 @@ +log4j.rootLogger=INFO, CONSOLE + +# CONSOLE is set to be a ConsoleAppender using a PatternLayout +log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender +log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout +log4j.appender.CONSOLE.layout.ConversionPattern=%d{HH:mm} [%-5p] %m%n + +# a more detailed PatternLayout: %d [%t] %-5p %c - %m%n + +log4j.logger.com.databricks=TRACE + +# Uncomment for debug logs from Apache HTTP client +log4j.logger.org.apache.http=DEBUG