Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Fail to run in native image #849

Open
luooyii opened this issue Aug 1, 2024 · 5 comments
Open

[Bug] Fail to run in native image #849

luooyii opened this issue Aug 1, 2024 · 5 comments
Labels
confidential-client For issues related to confidential client apps Feature Request Request for new functionality Work-around Provided Issue has a known work-around, which could one day be integrated into MSAL Java

Comments

@luooyii
Copy link

luooyii commented Aug 1, 2024

Library version used

1.16.0

Java version

21

Scenario

ConfidentialClient - service to service (AcquireTokenForClient)

Is this a new or an existing app?

The app is in production, I haven't upgraded MSAL, but started seeing this issue

Issue description and reproduction steps

I am trying to AOT compile a legacy service to native image. Everything works well when it runs in JIT(jar) mode. But when it runs in AOT mode. I throws this exception.

Cannot construct instance of com.microsoft.aad.msal4j.AadInstanceDiscoveryResponse: cannot deserialize from Object value (no delegate- or property-based Creator): this appears to be a native image, in which case you may need to configure reflection for the class that is to be deserialized

After that, I used native-image-agent to try to capture all reflections. And here are all msal4j reflections in my project.

{
  "name":"com.microsoft.aad.msal4j.AadInstanceDiscoveryResponse",
  "allDeclaredFields":true,
  "queryAllDeclaredMethods":true,
  "queryAllDeclaredConstructors":true,
  "methods":[{"name":"<init>","parameterTypes":[] }]
},
{
  "name":"com.microsoft.aad.msal4j.ConfidentialClientApplication"
},
{
  "name":"com.microsoft.aad.msal4j.InstanceDiscoveryMetadataEntry",
  "allDeclaredFields":true,
  "queryAllDeclaredMethods":true,
  "queryAllDeclaredConstructors":true,
  "methods":[{"name":"<init>","parameterTypes":[] }]
},
{
  "name":"[Lcom.microsoft.aad.msal4j.InstanceDiscoveryMetadataEntry;"
},

Normally, I just need to configure them at compile time to fix this. However, in general, in Java projects, we usually choose to configure reflection programmatically. However many classes are not public.

'com.microsoft.aad.msal4j.AadInstanceDiscoveryResponse' is not public in 'com.microsoft.aad.msal4j'. Cannot be accessed from outside package

I was wondering if these classes could be exposed?
Or maybe we can introduce native image meta info in msal4j lib? Because if I use the native-image-agent, it only captures the reflections which are running. But I cannot cover all the scenarios of Azure AD Auth. It means that each time I want to introduce a new scenario, I have to reuse to native-image-agent and compare the difference with the legacy reflection configurations.

Relevant code snippets

No response

Expected behavior

No response

Identity provider

Microsoft Entra ID (Work and School accounts and Personal Microsoft accounts)

Regression

No response

Solution and workarounds

No response

@luooyii luooyii added needs attention Automatically used when an issue is created through an issue template untriaged Automatically used when an issue is created through an issue template labels Aug 1, 2024
@luooyii luooyii changed the title [Bug] Not able to programmatically configure native image reflection [Bug] Fail to run in native image Aug 1, 2024
@Avery-Dunn Avery-Dunn added Requires more info More information is needed, from either the person who opened the issue or another team and removed needs attention Automatically used when an issue is created through an issue template untriaged Automatically used when an issue is created through an issue template labels Aug 1, 2024
@bgavrilMS bgavrilMS added Feature Request Request for new functionality Question Any questions about how MSAL Java works answered and removed Requires more info More information is needed, from either the person who opened the issue or another team Feature Request Request for new functionality labels Aug 5, 2024
@bgavrilMS
Copy link
Member

Right, MSAL 4j uses json deserialization for those objects. I reckon the AOT compiler uses an aggressive linker and strips away the objects AadInstanceDiscoveryResponse etc. These objects are not directly constructed by MSAL, but the json library will initiaze them via reflection. This ussually trips linkers up.

We cannot make these objects public. And I am not aware of a json serializer library that can use source generation (pls suggest one), but from experience this is a lot of work. We had to do this for MSAL.NET to be AOT-able.

Recommendation is to read up on the AOT linker and see if you can manually instruct it to not remove those objects. Or just ask the linker to not optimize MSAL 4j, it's not such a big library anyway.

@luooyii
Copy link
Author

luooyii commented Aug 5, 2024

Right, MSAL 4j uses json deserialization for those objects. I reckon the AOT compiler uses an aggressive linker and strips away the objects AadInstanceDiscoveryResponse etc. These objects are not directly constructed by MSAL, but the json library will initiaze them via reflection. This ussually trips linkers up.

We cannot make these objects public. And I am not aware of a json serializer library that can use source generation (pls suggest one), but from experience this is a lot of work. We had to do this for MSAL.NET to be AOT-able.

Recommendation is to read up on the AOT linker and see if you can manually instruct it to not remove those objects. Or just ask the linker to not optimize MSAL 4j, it's not such a big library anyway.

I am not sure if it is the one you wanted. This is a embeded command in gravvl vm. You can use this command to run a JIT jar file. And then it would collect relections or resources. Please note that finally you should use ctrl + c to stop the program, rather than close or kill the program directly.
java -agentlib:native-image-agent=config-merge-dir=./agent-output -jar ./app.jar

Finally some json config would be generated. After trimed the json file and copy them to META-INF/native-image, I started the AOT output successfully. This can be used as a temporary solution, still expect to be able to get the final solution from the official.

@bgavrilMS bgavrilMS added Feature Request Request for new functionality public-client For questions/issues related to public client apps confidential-client For issues related to confidential client apps Work-around Provided Issue has a known work-around, which could one day be integrated into MSAL Java and removed Question Any questions about how MSAL Java works answered public-client For questions/issues related to public client apps labels Aug 5, 2024
@bgavrilMS
Copy link
Member

We will keep the request on the backlog @luooyii and look for others requesting this feature. Not planning to address this soon.

@luooyii luooyii closed this as completed Aug 5, 2024
@luooyii luooyii reopened this Aug 5, 2024
@luooyii
Copy link
Author

luooyii commented Aug 5, 2024

Thanks @bgavrilMS

@yogeshVU
Copy link

This will be great feature to add to have. Our use-case requires uploading bunch of data to the blobstorage and uses confidential client. However, the startup time for invoking the jar slows down the upload process for each invocation. Having the AOT will be great.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confidential-client For issues related to confidential client apps Feature Request Request for new functionality Work-around Provided Issue has a known work-around, which could one day be integrated into MSAL Java
Projects
None yet
Development

No branches or pull requests

4 participants