I’m having Java issues with Microsoft authentication library https://github.com/AzureAD/microsoft-authentication-library-for-java I’m starting from this code:
IClientCredential credential = ClientCredentialFactory.createFromSecret(CLIENT_SECRET);
ConfidentialClientApplication app =
ConfidentialClientApplication
.builder(PUBLIC_CLIENT_ID, credential)
.authority(AUTHORITY)
.build();
I have translated this to
(let [credential (ClientCredentialFactory/createFromSecret secret-value)
builder ^ConfidentialClientApplication$Builder
(ConfidentialClientApplication/builder client-id credential)]
(->
builder
(.authority authority)
(.build)))
But I’m getting this exception:
; (err) Execution error (IllegalArgumentException) at nosco.azure/eval85548 (REPL:35).
; (err) No matching method authority found taking 1 args for class com.microsoft.aad.msal4j.ConfidentialClientApplication$Builder
I can see that authority method in the https://javadoc.io/static/com.microsoft.azure/msal4j/1.8.1/com/microsoft/aad/msal4j/ConfidentialClientApplication.Builder.html#authority-java.lang.String- but on using the clojure reflect facilities it doesn’t show…
Turning on reflection warnings says:
call to method authority on com.microsoft.aad.msal4j.ConfidentialClientApplication$Builder can't be resolved (argument types: java.lang.String).
Hm, here’s the culprit: https://github.com/AzureAD/microsoft-authentication-library-for-java/blob/dev/src/main/java/com/microsoft/aad/msal4j/AbstractClientApplicationBase.java some fancy annotations from something called Lombok
Lombok .... rolls eyes
Well at least they had the source available... saved me another day of fumbling in the dark.
@alexmiller I take it it’s a known thing? Can I brute force my way around it? I just want to do a PoC this time round.
This looks to be a thick layer on top of some http apis anyway so I might just go underneath eventually but I was hoping for a quick demo.
Lombok is all about pretending Java was less cumbersome to use
by giving you alternate syntax (hey, just use Clojure!) :)
but it may be obscuring what the actual method looks like
is the real method maybe getAuthority()?
or setAuthority() ?
(->
(r/reflect ConfidentialClientApplication$Builder)
:members
(->> (map :name)))
might be useful to use the reflection API directly and see what the actual methods are (or use clojure.reflect/reflect)
(com.microsoft.aad.msal4j.ConfidentialClientApplication$Builder
build
access$000
com.microsoft.aad.msal4j.ConfidentialClientApplication$Builder
build
clientCredential
self
sendX5c
self
access$100
sendX5c)
This is what I found confusing, I tried the reflection at first but this is the names of the members…
members are fields I think here
oh, I guess it's methods and fields
Yeah… well actually going to the ancestor (the base class) yields these members:
(aadInstanceDiscoveryResponse
aadInstanceDiscoveryResponse
access$000
access$100
access$1000
access$1100
access$1200
access$1300
access$1400
access$1500
access$1600
access$1700
access$1800
access$200
access$300
access$400
access$500
access$600
access$700
access$800
access$900
applicationName
applicationName
applicationVersion
applicationVersion
authenticationAuthority
authority
authority
b2cAuthority
build
clientCapabilities
clientCapabilities
clientId
com.microsoft.aad.msal4j.AbstractClientApplicationBase$Builder
connectTimeoutForDefaultHttpClient
connectTimeoutForDefaultHttpClient
correlationId
correlationId
createDefaultAADAuthority
executorService
executorService
httpClient
httpClient
logPii
logPii
onlySendFailureTelemetry
onlySendFailureTelemetry
proxy
proxy
readTimeoutForDefaultHttpClient
readTimeoutForDefaultHttpClient
self
setTokenCacheAccessAspect
sslSocketFactory
sslSocketFactory
telemetryConsumer
telemetryConsumer
tokenCacheAccessAspect
validateAuthority
validateAuthority)
OK, I think I’ve found it:
{:name authority,
:type java.lang.String,
:declaring-class
com.microsoft.aad.msal4j.AbstractClientApplicationBase$Builder,
:flags #{:private}}
{:name authority,
:return-type
com.microsoft.aad.msal4j.AbstractClientApplicationBase$Builder,
:declaring-class
com.microsoft.aad.msal4j.AbstractClientApplicationBase$Builder,
:parameter-types [java.lang.String],
:exception-types [java.net.MalformedURLException],
:flags #{:public}}
so there is a both a private field named authority and a public method, but they’re both on the parent abstract class
that should be fine
. prefers method if both exist
(.- is always field)
Still doesn’t work though 😞
did you try type-hinting the arg to ^String? I doubt that would help since it's reporting it as String already, but I dunno
I’ve hinted yeah
I should be able to do (.-authority builder)
right? but that throws the same exception
well it's private
True
without really diving into guts of the reflection code, I can't really tell what's wrong
if you can file a repro at http://ask.clojure.org I will eventually look at it but can't atm
Is there any workaround you could think of? I could perhaps use reflection to make the field private and set it manually?
I’ll file a repro. Does a git repo work for you or perhaps a deps.edn with a single .clj file?
or this is a variant of https://clojure.atlassian.net/browse/CLJ-1243
seems different than that though
ideally repro would be a clj -Sdeps ...
and some code I can run with that
Hm, the javadoc shows T
as the return argument for those. So perhaps they are generic.
I need to run, thanks @alexmiller for helping me figuring out some parts.
I’ll file a repro tomorrow. Have a great day!