Welcome! Please see the About page for a little more info on how this works.

0 votes
in Java Interop by
edited by

I want to turn this Java code into Clojure


The Problem: .seviceConfiguration takes a java.util.function.Conumser.

default B serviceConfiguration(Consumer<S3Configuration.Builder> serviceConfiguration)

The .servcieConfiguration method is defined here AWS SDK serviceConfiguration

I tried to use reify without much luck.

Maybe someone can point me into the right direction, or has already used this specific part of the API.

And can someone tell me why, is an API design like this advantageous for Java Developers, what is the point of this Construct?

1 Answer

0 votes
selected by
Best answer

Given the Java code, the .build() method on the third line must also return an instance of Consumer. So there's no need to reify anything, you should be able to use this:

(let [consumer (-> (S3Configuration/builder) (.pathStyleAccessEnabled true) (.build))]
  (-> (S3Client/builder) (.seviceConfiguration consumer) (.build)))

This pattern, where you create a builder, call a bunch of configuration methods on it, and then call .build to get the final object that you actually need, is called a... "builder". :) In the OOP world, it's quite helpful when you want to ensure encapsulation and that there are no partially built objects. It can also help in cases where you need to have multiple different builder using the same interface that behave differently. Or in cases where you have to separate creation of an object across different contexts.

Thank you for your answer. This was also my first approach.

But running running this code example above leads to the following Exception:

; (err) Execution error (ClassCastException) at java.lang.Class/cast (Class.java:3889).
; (err) Cannot cast software.amazon.awssdk.services.s3.S3Configuration to java.util.function.Consumer

This is why i tried to use reify

To clarify: I meant why would the even need a Consumer in their Method, what is the point of having this signature:
`(Consumer<S3Configuration.Builder> serviceConfiguration)`

Thank you for taking the time.
I see. Putting errors into the original post is often helpful. ;) The `serviceConfiguration` method has two signatures - one accepts an instance of `Consumer`, the other accepts an instance of `S3Configuration`. You can try to coax Clojure compiler into using the second signature by using `(.serviceConfiguration ^S3Configuration consumer)`.

Regarding your "what's the point" question - I don't know since that question is about the AWS JDK itself and not about Java in general.
Adding the typehint works. Thank you!

Out of curiosity, is there no simple way to create a Consumer out of it?
Those are completely different interfaces, so no direct way. But you can use `reify` to create an object that implements `Consumer` and maybe somehow use the configuration there.