From 3279e35c53b037d75958593cef97da62fe0b6ce2 Mon Sep 17 00:00:00 2001 From: Jon Amireh <2724407+jonamireh@users.noreply.github.com> Date: Mon, 8 Jun 2026 15:32:57 -0700 Subject: [PATCH 1/6] Add `DbxRequest` generation with `--call-request` --- core/api/core.api | 4 + core/build.gradle | 1 + .../core/stone/test/DbxTestTestRequests.java | 111 ++++++++++++++++++ core/generator/java/java.stoneg.py | 44 +++++++ .../java/com/dropbox/core/DbxRequest.java | 19 +++ .../core/stone/DbxRequestMethodTest.java | 55 +++++++++ .../com/dropbox/stone/java/StoneTask.kt | 4 + .../dropbox/stone/java/model/StoneConfig.kt | 1 + 8 files changed, 239 insertions(+) create mode 100644 core/src/main/java/com/dropbox/core/DbxRequest.java create mode 100644 core/src/test/java/com/dropbox/core/stone/DbxRequestMethodTest.java diff --git a/core/api/core.api b/core/api/core.api index 8eb6966e3..83a435287 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -135,6 +135,10 @@ public class com/dropbox/core/DbxPKCEWebAuth { public fun finishFromRedirect (Ljava/lang/String;Lcom/dropbox/core/DbxSessionStore;Ljava/util/Map;)Lcom/dropbox/core/DbxAuthFinish; } +public abstract interface class com/dropbox/core/DbxRequest { + public abstract fun call ()Ljava/lang/Object; +} + public class com/dropbox/core/DbxRequestConfig { public fun (Ljava/lang/String;)V public fun (Ljava/lang/String;Ljava/lang/String;)V diff --git a/core/build.gradle b/core/build.gradle index 1fe17fe26..e9e76d973 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -306,6 +306,7 @@ tasks.named("generateTestStone", StoneTask) { ), new StoneConfig( packageName: packageName, + callRequest: true, client: new ClientSpec( name: 'DbxClientV2Base', javadoc: 'TestClass.', diff --git a/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/DbxTestTestRequests.java b/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/DbxTestTestRequests.java index 0a48582cb..c7e9f1617 100644 --- a/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/DbxTestTestRequests.java +++ b/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/DbxTestTestRequests.java @@ -6,6 +6,7 @@ import com.dropbox.core.DbxApiException; import com.dropbox.core.DbxDownloader; import com.dropbox.core.DbxException; +import com.dropbox.core.DbxRequest; import com.dropbox.core.DbxUploader; import com.dropbox.core.DbxWrappedException; import com.dropbox.core.http.HttpRequestor; @@ -77,6 +78,21 @@ public DbxDownloader testDownload(String name, String breed) throws DbxApi return testDownload(_arg, Collections.emptyList()); } + /** + * See {@link DbxTestTestRequests#testDownload(String,String)}. + * + * @param name Used in {@link + * DbxTestTestRequests#testRouteV2(String,Date)}. Must not be {@code + * null}. + * @param breed Must not be {@code null}. + * + * @return A {@link DbxRequest} that can be executed later to obtain the + * result. + */ + public DbxRequest> testDownloadRequest(String name, String breed) { + return () -> testDownload(name, breed); + } + /** * * @param name Used in {@link @@ -138,6 +154,20 @@ public DbxDownloader testDownloadV2(UninitializedReason reason, String ses return testDownloadV2(_arg, Collections.emptyList()); } + /** + * See {@link + * DbxTestTestRequests#testDownloadV2(UninitializedReason,String)}. + * + * @param reason Must not be {@code null}. + * @param sessionId Must not be {@code null}. + * + * @return A {@link DbxRequest} that can be executed later to obtain the + * result. + */ + public DbxRequest> testDownloadV2Request(UninitializedReason reason, String sessionId) { + return () -> testDownloadV2(reason, sessionId); + } + /** * * @param reason Must not be {@code null}. @@ -175,6 +205,16 @@ public void testRoute() throws DbxApiException, DbxException { } } + /** + * See {@link DbxTestTestRequests#testRoute}. + * + * @return A {@link DbxRequest} that can be executed later to obtain the + * result. + */ + public DbxRequest testRouteRequest() { + return () -> { testRoute(); return null; }; + } + // // route 2/test/test_route_v2 // @@ -211,6 +251,20 @@ public void testRouteV2(String name) throws ParentUnionException, DbxException { testRouteV2(_arg); } + /** + * See {@link DbxTestTestRequests#testRouteV2(String,Date)}. + * + * @param name Used in {@link + * DbxTestTestRequests#testRouteV2(String,Date)}. Must not be {@code + * null}. + * + * @return A {@link DbxRequest} that can be executed later to obtain the + * result. + */ + public DbxRequest testRouteV2Request(String name) { + return () -> { testRouteV2(name); return null; }; + } + /** * * @param name Used in {@link @@ -225,6 +279,20 @@ public void testRouteV2(String name, Date born) throws ParentUnionException, Dbx testRouteV2(_arg); } + /** + * See {@link DbxTestTestRequests#testRouteV2(String,Date)}. + * + * @param name Used in {@link + * DbxTestTestRequests#testRouteV2(String,Date)}. Must not be {@code + * null}. + * + * @return A {@link DbxRequest} that can be executed later to obtain the + * result. + */ + public DbxRequest testRouteV2Request(String name, Date born) { + return () -> { testRouteV2(name, born); return null; }; + } + // // route 2/test/test_upload // @@ -258,6 +326,19 @@ public TestUploadUploader testUpload(UninitializedReason reason, String sessionI return testUpload(_arg); } + /** + * See {@link DbxTestTestRequests#testUpload(UninitializedReason,String)}. + * + * @param reason Must not be {@code null}. + * @param sessionId Must not be {@code null}. + * + * @return A {@link DbxRequest} that can be executed later to obtain the + * result. + */ + public DbxRequest testUploadRequest(UninitializedReason reason, String sessionId) { + return () -> testUpload(reason, sessionId); + } + // // route 2/test/test_upload_v2 // @@ -293,6 +374,21 @@ public TestUploadV2Uploader testUploadV2(String name, String breed) throws DbxEx return testUploadV2(_arg); } + /** + * See {@link DbxTestTestRequests#testUploadV2(String,String)}. + * + * @param name Used in {@link + * DbxTestTestRequests#testRouteV2(String,Date)}. Must not be {@code + * null}. + * @param breed Must not be {@code null}. + * + * @return A {@link DbxRequest} that can be executed later to obtain the + * result. + */ + public DbxRequest testUploadV2Request(String name, String breed) { + return () -> testUploadV2(name, breed); + } + /** * * @param name Used in {@link @@ -346,6 +442,21 @@ public TestUploadV3Uploader testUploadV3(String name, String breed) throws DbxEx return testUploadV3(_arg); } + /** + * See {@link DbxTestTestRequests#testUploadV3(String,String)}. + * + * @param name Used in {@link + * DbxTestTestRequests#testRouteV2(String,Date)}. Must not be {@code + * null}. + * @param breed Must not be {@code null}. + * + * @return A {@link DbxRequest} that can be executed later to obtain the + * result. + */ + public DbxRequest testUploadV3Request(String name, String breed) { + return () -> testUploadV3(name, breed); + } + /** * * @param name Used in {@link diff --git a/core/generator/java/java.stoneg.py b/core/generator/java/java.stoneg.py index 544b06896..efb45ce1a 100644 --- a/core/generator/java/java.stoneg.py +++ b/core/generator/java/java.stoneg.py @@ -621,6 +621,8 @@ def __lt__(self, other): 'exist.') _CMDLINE_PARSER.add_argument('--unused-classes-to-generate', default=None, help='Specify types ' + 'that we want to generate regardless of whether they are used.') +_CMDLINE_PARSER.add_argument('--call-request', action="store_true", default=False, + help='Generate additional *Request methods that return DbxRequest.') class JavaCodeGenerator(CodeBackend): @@ -729,6 +731,8 @@ def add_imports_for_namespace(self, namespace): 'java.util.HashMap', 'java.util.Map', ) + if self._j._args.call_request: + self.add_imports('com.dropbox.core.DbxRequest') for route in namespace.routes: self.add_imports_for_route(route) @@ -2800,6 +2804,12 @@ def generate_route_base(self, route, force_public=False): else: assert False, "unrecognized route request style: %s" % j.request_style(route) + if is_public and self.g.args.call_request: + request_args = w.fmt('%s arg', j.java_class(route.arg_data_type)) if j.has_arg(route) else '' + request_arg_names = 'arg' if j.has_arg(route) else '' + self._emit_request_method_body(route, request_args, request_arg_names, return_class, + params=params) + def generate_route(self, route, required_only=True): assert isinstance(route, ApiRoute), repr(route) @@ -2914,6 +2924,15 @@ def generate_route(self, route, required_only=True): else: w.out('%s(_arg);', j.route_method(route)) + if self.g.args.call_request: + request_args = ', '.join( + w.fmt('%s %s', j.java_class(f), j.param_name(f)) for f in fields + ) + request_arg_names = ', '.join(j.param_name(f) for f in fields) + request_params = w._javadoc_fields(fields, route, allow_defaults=False) + self._emit_request_method_body(route, request_args, request_arg_names, return_class, + params=request_params) + def generate_route_builder_method(self, route): assert isinstance(route, ApiRoute), repr(route) @@ -2953,6 +2972,31 @@ def generate_route_builder_method(self, route): else: w.out('return new %s(this, %s);', return_class, builder_args) + def _emit_request_method_body(self, route, args, arg_names, return_class, fields=(), params=()): + """Emit the request method signature and body.""" + w = self.w + j = self.j + + if return_class == JavaClass('void'): + boxed_return = JavaClass('java.lang.Void') + else: + boxed_return = return_class + + request_class = JavaClass('com.dropbox.core.DbxRequest', generics=(boxed_return,)) + method_name = j.route_method(route) + 'Request' + + w.out('') + returns_doc = "A %s that can be executed later to obtain the result." % ( + w.javadoc_ref(JavaClass('com.dropbox.core.DbxRequest')), + ) + doc = "See %s." % w.javadoc_ref(route) + w.javadoc(doc, params=params, returns=returns_doc) + with w.block('public %s %s(%s)', request_class, method_name, args): + if return_class == JavaClass('void'): + w.out('return () -> { %s(%s); return null; };', j.route_method(route), arg_names) + else: + w.out('return () -> %s(%s);', j.route_method(route), arg_names) + def translate_error_wrapper(self, route, error_wrapper_var): assert isinstance(route, ApiRoute), repr(route) assert isinstance(error_wrapper_var, str), repr(error_wrapper_var) diff --git a/core/src/main/java/com/dropbox/core/DbxRequest.java b/core/src/main/java/com/dropbox/core/DbxRequest.java new file mode 100644 index 000000000..907d40cd9 --- /dev/null +++ b/core/src/main/java/com/dropbox/core/DbxRequest.java @@ -0,0 +1,19 @@ +package com.dropbox.core; + +/** + * A functional interface representing a request that produces a result and may throw a checked + * exception. Similar to {@link java.util.concurrent.Callable}, but intended for use in contexts + * where the operation represents an API request. + * + * @param the type of result produced by this request + */ +@FunctionalInterface +public interface DbxRequest { + /** + * Executes the request and returns the result. + * + * @return the result of the request + * @throws Exception if the request fails + */ + T call() throws Exception; +} diff --git a/core/src/test/java/com/dropbox/core/stone/DbxRequestMethodTest.java b/core/src/test/java/com/dropbox/core/stone/DbxRequestMethodTest.java new file mode 100644 index 000000000..825aa887d --- /dev/null +++ b/core/src/test/java/com/dropbox/core/stone/DbxRequestMethodTest.java @@ -0,0 +1,55 @@ +package com.dropbox.core.stone; + +import static org.mockito.Mockito.*; + +import com.dropbox.core.DbxDownloader; +import com.dropbox.core.DbxRequest; +import com.dropbox.core.stone.test.DbxTestTestRequests; +import com.dropbox.core.stone.test.Fish; +import com.dropbox.core.stone.test.TestUploadUploader; +import com.dropbox.core.stone.test.UninitializedReason; +import com.dropbox.core.v2.DbxRawClientV2; + +import org.mockito.Mockito; +import org.testng.annotations.Test; + +import static org.testng.Assert.*; + +public class DbxRequestMethodTest { + + @Test + public void testVoidRouteRequestReturnsDbxRequest() { + DbxRawClientV2 mockClient = mock(DbxRawClientV2.class, RETURNS_DEEP_STUBS); + DbxTestTestRequests requests = new DbxTestTestRequests(mockClient); + + DbxRequest request = requests.testRouteRequest(); + assertNotNull(request); + } + + @Test + public void testDownloadRouteRequestReturnsDbxRequest() { + DbxRawClientV2 mockClient = mock(DbxRawClientV2.class, RETURNS_DEEP_STUBS); + DbxTestTestRequests requests = new DbxTestTestRequests(mockClient); + + DbxRequest> request = requests.testDownloadRequest("fido", "lab"); + assertNotNull(request); + } + + @Test + public void testUploadRouteRequestReturnsDbxRequest() { + DbxRawClientV2 mockClient = mock(DbxRawClientV2.class, RETURNS_DEEP_STUBS); + DbxTestTestRequests requests = new DbxTestTestRequests(mockClient); + + DbxRequest request = requests.testUploadRequest(UninitializedReason.BAD_REQUEST, "session123"); + assertNotNull(request); + } + + @Test + public void testRouteV2RequestWithParams() { + DbxRawClientV2 mockClient = mock(DbxRawClientV2.class, RETURNS_DEEP_STUBS); + DbxTestTestRequests requests = new DbxTestTestRequests(mockClient); + + DbxRequest request = requests.testRouteV2Request("buddy"); + assertNotNull(request); + } +} diff --git a/stone-java-gradle-plugin/src/main/kotlin/com/dropbox/stone/java/StoneTask.kt b/stone-java-gradle-plugin/src/main/kotlin/com/dropbox/stone/java/StoneTask.kt index f202d1c43..0740c7c9f 100644 --- a/stone-java-gradle-plugin/src/main/kotlin/com/dropbox/stone/java/StoneTask.kt +++ b/stone-java-gradle-plugin/src/main/kotlin/com/dropbox/stone/java/StoneTask.kt @@ -125,6 +125,10 @@ abstract class StoneTask : DefaultTask() { generatorArgs.addAll(generatorArgs.indexOf(":all") + 1, listOf("--filter-by-route-attr", buildRouteFilter(stoneConfig))) } + if (stoneConfig.callRequest) { + generatorArgs += "--call-request" + } + if (stoneConfig.dataTypesOnly) { generatorArgs += "--data-types-only" } else { diff --git a/stone-java-gradle-plugin/src/main/kotlin/com/dropbox/stone/java/model/StoneConfig.kt b/stone-java-gradle-plugin/src/main/kotlin/com/dropbox/stone/java/model/StoneConfig.kt index 501925ea5..c840e66d3 100644 --- a/stone-java-gradle-plugin/src/main/kotlin/com/dropbox/stone/java/model/StoneConfig.kt +++ b/stone-java-gradle-plugin/src/main/kotlin/com/dropbox/stone/java/model/StoneConfig.kt @@ -6,6 +6,7 @@ class StoneConfig( var packageName: String = "com.dropbox.stone", var globalRouteFilter: String? = null, var dataTypesOnly: Boolean = false, + var callRequest: Boolean = false, var client: ClientSpec? = null, var routeWhitelistFilter: String? = null, ) : Serializable \ No newline at end of file From 6d23a44c71c67a6f51b680e462014b1d19f14687 Mon Sep 17 00:00:00 2001 From: Jon Amireh <2724407+jonamireh@users.noreply.github.com> Date: Mon, 8 Jun 2026 15:49:45 -0700 Subject: [PATCH 2/6] Update javadoc --- .../core/stone/test/DbxTestTestRequests.java | 19 ++++++++----------- core/generator/java/java.stoneg.py | 11 ++++++++--- .../java/com/dropbox/core/DbxRequest.java | 2 +- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/DbxTestTestRequests.java b/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/DbxTestTestRequests.java index c7e9f1617..f155bcf14 100644 --- a/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/DbxTestTestRequests.java +++ b/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/DbxTestTestRequests.java @@ -87,7 +87,7 @@ public DbxDownloader testDownload(String name, String breed) throws DbxApi * @param breed Must not be {@code null}. * * @return A {@link DbxRequest} that can be executed later to obtain the - * result. + * {@code DbxDownloader<Fish>}. */ public DbxRequest> testDownloadRequest(String name, String breed) { return () -> testDownload(name, breed); @@ -162,7 +162,7 @@ public DbxDownloader testDownloadV2(UninitializedReason reason, String ses * @param sessionId Must not be {@code null}. * * @return A {@link DbxRequest} that can be executed later to obtain the - * result. + * {@code DbxDownloader<Fish>}. */ public DbxRequest> testDownloadV2Request(UninitializedReason reason, String sessionId) { return () -> testDownloadV2(reason, sessionId); @@ -208,8 +208,7 @@ public void testRoute() throws DbxApiException, DbxException { /** * See {@link DbxTestTestRequests#testRoute}. * - * @return A {@link DbxRequest} that can be executed later to obtain the - * result. + * @return A {@link DbxRequest} that can be executed later. */ public DbxRequest testRouteRequest() { return () -> { testRoute(); return null; }; @@ -258,8 +257,7 @@ public void testRouteV2(String name) throws ParentUnionException, DbxException { * DbxTestTestRequests#testRouteV2(String,Date)}. Must not be {@code * null}. * - * @return A {@link DbxRequest} that can be executed later to obtain the - * result. + * @return A {@link DbxRequest} that can be executed later. */ public DbxRequest testRouteV2Request(String name) { return () -> { testRouteV2(name); return null; }; @@ -286,8 +284,7 @@ public void testRouteV2(String name, Date born) throws ParentUnionException, Dbx * DbxTestTestRequests#testRouteV2(String,Date)}. Must not be {@code * null}. * - * @return A {@link DbxRequest} that can be executed later to obtain the - * result. + * @return A {@link DbxRequest} that can be executed later. */ public DbxRequest testRouteV2Request(String name, Date born) { return () -> { testRouteV2(name, born); return null; }; @@ -333,7 +330,7 @@ public TestUploadUploader testUpload(UninitializedReason reason, String sessionI * @param sessionId Must not be {@code null}. * * @return A {@link DbxRequest} that can be executed later to obtain the - * result. + * {@code TestUploadUploader}. */ public DbxRequest testUploadRequest(UninitializedReason reason, String sessionId) { return () -> testUpload(reason, sessionId); @@ -383,7 +380,7 @@ public TestUploadV2Uploader testUploadV2(String name, String breed) throws DbxEx * @param breed Must not be {@code null}. * * @return A {@link DbxRequest} that can be executed later to obtain the - * result. + * {@code TestUploadV2Uploader}. */ public DbxRequest testUploadV2Request(String name, String breed) { return () -> testUploadV2(name, breed); @@ -451,7 +448,7 @@ public TestUploadV3Uploader testUploadV3(String name, String breed) throws DbxEx * @param breed Must not be {@code null}. * * @return A {@link DbxRequest} that can be executed later to obtain the - * result. + * {@code TestUploadV3Uploader}. */ public DbxRequest testUploadV3Request(String name, String breed) { return () -> testUploadV3(name, breed); diff --git a/core/generator/java/java.stoneg.py b/core/generator/java/java.stoneg.py index efb45ce1a..5d6af0be9 100644 --- a/core/generator/java/java.stoneg.py +++ b/core/generator/java/java.stoneg.py @@ -2986,9 +2986,14 @@ def _emit_request_method_body(self, route, args, arg_names, return_class, fields method_name = j.route_method(route) + 'Request' w.out('') - returns_doc = "A %s that can be executed later to obtain the result." % ( - w.javadoc_ref(JavaClass('com.dropbox.core.DbxRequest')), - ) + dbx_request_ref = w.javadoc_ref(JavaClass('com.dropbox.core.DbxRequest')) + if return_class == JavaClass('void'): + returns_doc = "A %s that can be executed later." % dbx_request_ref + else: + result_type = w.resolved_class(boxed_return, generics=True) + returns_doc = "A %s that can be executed later to obtain the {@code %s}." % ( + dbx_request_ref, result_type, + ) doc = "See %s." % w.javadoc_ref(route) w.javadoc(doc, params=params, returns=returns_doc) with w.block('public %s %s(%s)', request_class, method_name, args): diff --git a/core/src/main/java/com/dropbox/core/DbxRequest.java b/core/src/main/java/com/dropbox/core/DbxRequest.java index 907d40cd9..a4f5acaba 100644 --- a/core/src/main/java/com/dropbox/core/DbxRequest.java +++ b/core/src/main/java/com/dropbox/core/DbxRequest.java @@ -1,7 +1,7 @@ package com.dropbox.core; /** - * A functional interface representing a request that produces a result and may throw a checked + * A functional interface representing a request that produces a result {@code } and may throw a checked * exception. Similar to {@link java.util.concurrent.Callable}, but intended for use in contexts * where the operation represents an API request. * From a14eafd21b308ed66d637b75be1be14b19049440 Mon Sep 17 00:00:00 2001 From: Jon Amireh <2724407+jonamireh@users.noreply.github.com> Date: Mon, 8 Jun 2026 16:12:03 -0700 Subject: [PATCH 3/6] Update Builders --- .../test/DbxTestTestUploadV3Builder.java | 11 ++++++++ .../core/stone/test/TestDownloadBuilder.java | 11 ++++++++ .../stone/test/TestDownloadV2Builder.java | 12 +++++++++ .../core/stone/test/TestUploadV2Builder.java | 11 ++++++++ core/generator/java/java.stoneg.py | 26 +++++++++++++++++++ 5 files changed, 71 insertions(+) diff --git a/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/DbxTestTestUploadV3Builder.java b/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/DbxTestTestUploadV3Builder.java index e8703bf9b..68137bf34 100644 --- a/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/DbxTestTestUploadV3Builder.java +++ b/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/DbxTestTestUploadV3Builder.java @@ -4,6 +4,7 @@ package com.dropbox.core.stone.test; import com.dropbox.core.DbxException; +import com.dropbox.core.DbxRequest; import com.dropbox.core.util.LangUtil; import com.dropbox.core.v2.DbxUploadStyleBuilder; @@ -65,4 +66,14 @@ public TestUploadV3Uploader start() throws ParentUnionException, DbxException { Dog arg_ = this._builder.build(); return _client.testUploadV3(arg_); } + + /** + * See {@link DbxTestTestRequests#testUploadV3(String,String)}. + * + * @return A {@link DbxRequest} that can be executed later to obtain the + * {@code TestUploadV3Uploader}. + */ + public DbxRequest startRequest() { + return () -> start(); + } } diff --git a/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/TestDownloadBuilder.java b/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/TestDownloadBuilder.java index a12567d07..4be0b7571 100644 --- a/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/TestDownloadBuilder.java +++ b/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/TestDownloadBuilder.java @@ -6,6 +6,7 @@ import com.dropbox.core.DbxApiException; import com.dropbox.core.DbxDownloader; import com.dropbox.core.DbxException; +import com.dropbox.core.DbxRequest; import com.dropbox.core.util.LangUtil; import com.dropbox.core.v2.DbxDownloadStyleBuilder; @@ -67,4 +68,14 @@ public DbxDownloader start() throws DbxApiException, DbxException { Dog arg_ = this._builder.build(); return _client.testDownload(arg_, getHeaders()); } + + /** + * See {@link DbxTestTestRequests#testDownload(String,String)}. + * + * @return A {@link DbxRequest} that can be executed later to obtain the + * {@code DbxDownloader<Fish>}. + */ + public DbxRequest> startRequest() { + return () -> start(); + } } diff --git a/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/TestDownloadV2Builder.java b/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/TestDownloadV2Builder.java index 4fa1a1297..e2baf7a91 100644 --- a/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/TestDownloadV2Builder.java +++ b/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/TestDownloadV2Builder.java @@ -5,6 +5,7 @@ import com.dropbox.core.DbxDownloader; import com.dropbox.core.DbxException; +import com.dropbox.core.DbxRequest; import com.dropbox.core.v2.DbxDownloadStyleBuilder; /** @@ -46,4 +47,15 @@ public DbxDownloader start() throws ParentUnionException, DbxException { Uninitialized arg_ = new Uninitialized(reason, sessionId); return _client.testDownloadV2(arg_, getHeaders()); } + + /** + * See {@link + * DbxTestTestRequests#testDownloadV2(UninitializedReason,String)}. + * + * @return A {@link DbxRequest} that can be executed later to obtain the + * {@code DbxDownloader<Fish>}. + */ + public DbxRequest> startRequest() { + return () -> start(); + } } diff --git a/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/TestUploadV2Builder.java b/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/TestUploadV2Builder.java index ac4044c9e..49cc57e49 100644 --- a/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/TestUploadV2Builder.java +++ b/core/build/generated_stone_source/test/src/com/dropbox/core/stone/test/TestUploadV2Builder.java @@ -4,6 +4,7 @@ package com.dropbox.core.stone.test; import com.dropbox.core.DbxException; +import com.dropbox.core.DbxRequest; import com.dropbox.core.util.LangUtil; import com.dropbox.core.v2.DbxUploadStyleBuilder; @@ -65,4 +66,14 @@ public TestUploadV2Uploader start() throws ParentUnionException, DbxException { Dog arg_ = this._builder.build(); return _client.testUploadV2(arg_); } + + /** + * See {@link DbxTestTestRequests#testUploadV2(String,String)}. + * + * @return A {@link DbxRequest} that can be executed later to obtain the + * {@code TestUploadV2Uploader}. + */ + public DbxRequest startRequest() { + return () -> start(); + } } diff --git a/core/generator/java/java.stoneg.py b/core/generator/java/java.stoneg.py index 5d6af0be9..138f346db 100644 --- a/core/generator/java/java.stoneg.py +++ b/core/generator/java/java.stoneg.py @@ -799,6 +799,9 @@ def add_imports_for_route_builder(self, route): elif j.request_style(route) == 'upload': self.add_imports('com.dropbox.core.v2.DbxUploadStyleBuilder') + if self._j._args.call_request: + self.add_imports('com.dropbox.core.DbxRequest') + def add_imports_for_route_uploader(self, route): self.add_imports( 'com.dropbox.core.DbxWrappedException', @@ -3897,6 +3900,29 @@ def generate_route_builder(self, route): else: w.out('_client.%s(%s);', j.route_method(route), ', '.join(args)) + if self.g.args.call_request: + if return_class == JavaClass('void'): + boxed_return = JavaClass('java.lang.Void') + else: + boxed_return = return_class + request_class = JavaClass('com.dropbox.core.DbxRequest', generics=(boxed_return,)) + + w.out('') + dbx_request_ref = w.javadoc_ref(JavaClass('com.dropbox.core.DbxRequest')) + if return_class == JavaClass('void'): + returns_doc = "A %s that can be executed later." % dbx_request_ref + else: + result_type = w.resolved_class(boxed_return, generics=True) + returns_doc = "A %s that can be executed later to obtain the {@code %s}." % ( + dbx_request_ref, result_type, + ) + w.javadoc("See %s." % w.javadoc_ref(route), returns=returns_doc) + with w.block('public %s startRequest()', request_class): + if return_class == JavaClass('void'): + w.out('return () -> { start(); return null; };') + else: + w.out('return () -> start();') + def generate_field_assignment(self, field, lhs=None, rhs=None, allow_default=True): assert isinstance(field, Field), repr(field) From 7a8ec04ef97e7bd0a28d42d55f40b8c4f42f8c67 Mon Sep 17 00:00:00 2001 From: Jon Amireh <2724407+jonamireh@users.noreply.github.com> Date: Mon, 8 Jun 2026 16:20:10 -0700 Subject: [PATCH 4/6] Cleanup --- core/generator/java/java.stoneg.py | 35 +++++++++--------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/core/generator/java/java.stoneg.py b/core/generator/java/java.stoneg.py index 138f346db..80319f53e 100644 --- a/core/generator/java/java.stoneg.py +++ b/core/generator/java/java.stoneg.py @@ -2975,7 +2975,8 @@ def generate_route_builder_method(self, route): else: w.out('return new %s(this, %s);', return_class, builder_args) - def _emit_request_method_body(self, route, args, arg_names, return_class, fields=(), params=()): + def _emit_request_method_body(self, route, args, arg_names, return_class, + fields=(), params=(), method_name=None, delegate=None): """Emit the request method signature and body.""" w = self.w j = self.j @@ -2986,7 +2987,10 @@ def _emit_request_method_body(self, route, args, arg_names, return_class, fields boxed_return = return_class request_class = JavaClass('com.dropbox.core.DbxRequest', generics=(boxed_return,)) - method_name = j.route_method(route) + 'Request' + if method_name is None: + method_name = j.route_method(route) + 'Request' + if delegate is None: + delegate = '%s(%s)' % (j.route_method(route), arg_names) w.out('') dbx_request_ref = w.javadoc_ref(JavaClass('com.dropbox.core.DbxRequest')) @@ -3001,9 +3005,9 @@ def _emit_request_method_body(self, route, args, arg_names, return_class, fields w.javadoc(doc, params=params, returns=returns_doc) with w.block('public %s %s(%s)', request_class, method_name, args): if return_class == JavaClass('void'): - w.out('return () -> { %s(%s); return null; };', j.route_method(route), arg_names) + w.out('return () -> { %s; return null; };', delegate) else: - w.out('return () -> %s(%s);', j.route_method(route), arg_names) + w.out('return () -> %s;', delegate) def translate_error_wrapper(self, route, error_wrapper_var): assert isinstance(route, ApiRoute), repr(route) @@ -3901,27 +3905,8 @@ def generate_route_builder(self, route): w.out('_client.%s(%s);', j.route_method(route), ', '.join(args)) if self.g.args.call_request: - if return_class == JavaClass('void'): - boxed_return = JavaClass('java.lang.Void') - else: - boxed_return = return_class - request_class = JavaClass('com.dropbox.core.DbxRequest', generics=(boxed_return,)) - - w.out('') - dbx_request_ref = w.javadoc_ref(JavaClass('com.dropbox.core.DbxRequest')) - if return_class == JavaClass('void'): - returns_doc = "A %s that can be executed later." % dbx_request_ref - else: - result_type = w.resolved_class(boxed_return, generics=True) - returns_doc = "A %s that can be executed later to obtain the {@code %s}." % ( - dbx_request_ref, result_type, - ) - w.javadoc("See %s." % w.javadoc_ref(route), returns=returns_doc) - with w.block('public %s startRequest()', request_class): - if return_class == JavaClass('void'): - w.out('return () -> { start(); return null; };') - else: - w.out('return () -> start();') + self._emit_request_method_body(route, '', '', return_class, + method_name='startRequest', delegate='start()') def generate_field_assignment(self, field, lhs=None, rhs=None, allow_default=True): assert isinstance(field, Field), repr(field) From 30cbb6e03ae30dc92df210ce665c637369d64021 Mon Sep 17 00:00:00 2001 From: Jon Amireh <2724407+jonamireh@users.noreply.github.com> Date: Tue, 9 Jun 2026 09:02:01 -0700 Subject: [PATCH 5/6] Switch to generateRequest --- core/build.gradle | 2 +- core/generator/java/java.stoneg.py | 12 ++++++------ .../main/kotlin/com/dropbox/stone/java/StoneTask.kt | 4 ++-- .../com/dropbox/stone/java/model/StoneConfig.kt | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index e9e76d973..cfee3c2e7 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -306,7 +306,7 @@ tasks.named("generateTestStone", StoneTask) { ), new StoneConfig( packageName: packageName, - callRequest: true, + generateRequest: true, client: new ClientSpec( name: 'DbxClientV2Base', javadoc: 'TestClass.', diff --git a/core/generator/java/java.stoneg.py b/core/generator/java/java.stoneg.py index 80319f53e..bcda84dd8 100644 --- a/core/generator/java/java.stoneg.py +++ b/core/generator/java/java.stoneg.py @@ -621,7 +621,7 @@ def __lt__(self, other): 'exist.') _CMDLINE_PARSER.add_argument('--unused-classes-to-generate', default=None, help='Specify types ' + 'that we want to generate regardless of whether they are used.') -_CMDLINE_PARSER.add_argument('--call-request', action="store_true", default=False, +_CMDLINE_PARSER.add_argument('--generate-request', action="store_true", default=False, help='Generate additional *Request methods that return DbxRequest.') @@ -731,7 +731,7 @@ def add_imports_for_namespace(self, namespace): 'java.util.HashMap', 'java.util.Map', ) - if self._j._args.call_request: + if self._j._args.generate_request: self.add_imports('com.dropbox.core.DbxRequest') for route in namespace.routes: self.add_imports_for_route(route) @@ -799,7 +799,7 @@ def add_imports_for_route_builder(self, route): elif j.request_style(route) == 'upload': self.add_imports('com.dropbox.core.v2.DbxUploadStyleBuilder') - if self._j._args.call_request: + if self._j._args.generate_request: self.add_imports('com.dropbox.core.DbxRequest') def add_imports_for_route_uploader(self, route): @@ -2807,7 +2807,7 @@ def generate_route_base(self, route, force_public=False): else: assert False, "unrecognized route request style: %s" % j.request_style(route) - if is_public and self.g.args.call_request: + if is_public and self.g.args.generate_request: request_args = w.fmt('%s arg', j.java_class(route.arg_data_type)) if j.has_arg(route) else '' request_arg_names = 'arg' if j.has_arg(route) else '' self._emit_request_method_body(route, request_args, request_arg_names, return_class, @@ -2927,7 +2927,7 @@ def generate_route(self, route, required_only=True): else: w.out('%s(_arg);', j.route_method(route)) - if self.g.args.call_request: + if self.g.args.generate_request: request_args = ', '.join( w.fmt('%s %s', j.java_class(f), j.param_name(f)) for f in fields ) @@ -3904,7 +3904,7 @@ def generate_route_builder(self, route): else: w.out('_client.%s(%s);', j.route_method(route), ', '.join(args)) - if self.g.args.call_request: + if self.g.args.generate_request: self._emit_request_method_body(route, '', '', return_class, method_name='startRequest', delegate='start()') diff --git a/stone-java-gradle-plugin/src/main/kotlin/com/dropbox/stone/java/StoneTask.kt b/stone-java-gradle-plugin/src/main/kotlin/com/dropbox/stone/java/StoneTask.kt index 0740c7c9f..13a794aa6 100644 --- a/stone-java-gradle-plugin/src/main/kotlin/com/dropbox/stone/java/StoneTask.kt +++ b/stone-java-gradle-plugin/src/main/kotlin/com/dropbox/stone/java/StoneTask.kt @@ -125,8 +125,8 @@ abstract class StoneTask : DefaultTask() { generatorArgs.addAll(generatorArgs.indexOf(":all") + 1, listOf("--filter-by-route-attr", buildRouteFilter(stoneConfig))) } - if (stoneConfig.callRequest) { - generatorArgs += "--call-request" + if (stoneConfig.generateRequest) { + generatorArgs += "--generate-request" } if (stoneConfig.dataTypesOnly) { diff --git a/stone-java-gradle-plugin/src/main/kotlin/com/dropbox/stone/java/model/StoneConfig.kt b/stone-java-gradle-plugin/src/main/kotlin/com/dropbox/stone/java/model/StoneConfig.kt index c840e66d3..913abbea3 100644 --- a/stone-java-gradle-plugin/src/main/kotlin/com/dropbox/stone/java/model/StoneConfig.kt +++ b/stone-java-gradle-plugin/src/main/kotlin/com/dropbox/stone/java/model/StoneConfig.kt @@ -6,7 +6,7 @@ class StoneConfig( var packageName: String = "com.dropbox.stone", var globalRouteFilter: String? = null, var dataTypesOnly: Boolean = false, - var callRequest: Boolean = false, + var generateRequest: Boolean = false, var client: ClientSpec? = null, var routeWhitelistFilter: String? = null, ) : Serializable \ No newline at end of file From 511564ed90c2828e450603af8fc8f0cefe291b8f Mon Sep 17 00:00:00 2001 From: Jon Amireh <2724407+jonamireh@users.noreply.github.com> Date: Tue, 9 Jun 2026 11:22:02 -0700 Subject: [PATCH 6/6] Implement Callable instead --- .../src/main/java/com/dropbox/core/DbxRequest.java | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/com/dropbox/core/DbxRequest.java b/core/src/main/java/com/dropbox/core/DbxRequest.java index a4f5acaba..5e1a44169 100644 --- a/core/src/main/java/com/dropbox/core/DbxRequest.java +++ b/core/src/main/java/com/dropbox/core/DbxRequest.java @@ -1,19 +1,13 @@ package com.dropbox.core; +import java.util.concurrent.Callable; + /** * A functional interface representing a request that produces a result {@code } and may throw a checked - * exception. Similar to {@link java.util.concurrent.Callable}, but intended for use in contexts + * exception. Extends {@link java.util.concurrent.Callable} but is intended for use in contexts * where the operation represents an API request. * * @param the type of result produced by this request */ @FunctionalInterface -public interface DbxRequest { - /** - * Executes the request and returns the result. - * - * @return the result of the request - * @throws Exception if the request fails - */ - T call() throws Exception; -} +public interface DbxRequest extends Callable { }