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

Many "Failed to index" warnings since 3.9.1 #40153

Closed
famod opened this issue Apr 19, 2024 · 35 comments · Fixed by #40448
Closed

Many "Failed to index" warnings since 3.9.1 #40153

famod opened this issue Apr 19, 2024 · 35 comments · Fixed by #40448
Labels
area/rest kind/bug Something isn't working
Milestone

Comments

@famod
Copy link
Member

famod commented Apr 19, 2024

Describe the bug

Since 3.9.1 I'm getting the following warnings when building my app or running dev mode:

[WARNING] [io.quarkus.deployment.index.IndexWrapper] Failed to index org.springframework.context.support.AbstractApplicationContext: Class does not exist in ClassLoader QuarkusClassLoader:Deployment Class Loader: PROD for myapp-5.0.1.local-dev1@62d7d954
[WARNING] [io.quarkus.deployment.index.IndexWrapper] Failed to index com.sun.xml.fastinfoset.stax.StAXDocumentParser: Class does not exist in ClassLoader QuarkusClassLoader:Deployment Class Loader: PROD for myapp-5.0.1.local-dev1@62d7d954
[WARNING] [io.quarkus.deployment.index.IndexWrapper] Failed to index com.sun.xml.fastinfoset.stax.StAXDocumentSerializer: Class does not exist in ClassLoader QuarkusClassLoader:Deployment Class Loader: PROD for myapp-5.0.1.local-dev1@62d7d954
[WARNING] [io.quarkus.deployment.index.IndexWrapper] Failed to index org.springframework.context.ConfigurableApplicationContext: Class does not exist in ClassLoader QuarkusClassLoader:Deployment Class Loader: PROD for myapp-5.0.1.local-dev1@62d7d954
[WARNING] [io.quarkus.deployment.index.IndexWrapper] Failed to index io.mashona.logwriting.ArrayStore: Class does not exist in ClassLoader QuarkusClassLoader:Deployment Class Loader: PROD for myapp-5.0.1.local-dev1@62d7d954
[WARNING] [io.quarkus.deployment.index.IndexWrapper] Failed to index org.apache.activemq.artemis.core.journal.RecordInfo: Class does not exist in ClassLoader QuarkusClassLoader:Deployment Class Loader: PROD for myapp-5.0.1.local-dev1@62d7d954
[WARNING] [io.quarkus.deployment.index.IndexWrapper] Failed to index org.apache.activemq.artemis.core.journal.Journal: Class does not exist in ClassLoader QuarkusClassLoader:Deployment Class Loader: PROD for myapp-5.0.1.local-dev1@62d7d954
[WARNING] [io.quarkus.deployment.index.IndexWrapper] Failed to index jakarta.jms.XAConnection: Class does not exist in ClassLoader QuarkusClassLoader:Deployment Class Loader: PROD for myapp-5.0.1.local-dev1@62d7d954
[WARNING] [io.quarkus.deployment.index.IndexWrapper] Failed to index jakarta.jms.XASession: Class does not exist in ClassLoader QuarkusClassLoader:Deployment Class Loader: PROD for myapp-5.0.1.local-dev1@62d7d954
[WARNING] [io.quarkus.deployment.index.IndexWrapper] Failed to index jakarta.jms.XAConnectionFactory: Class does not exist in ClassLoader QuarkusClassLoader:Deployment Class Loader: PROD for myapp-5.0.1.local-dev1@62d7d954
[WARNING] [io.quarkus.deployment.index.IndexWrapper] Failed to index jakarta.jms.Connection: Class does not exist in ClassLoader QuarkusClassLoader:Deployment Class Loader: PROD for myapp-5.0.1.local-dev1@62d7d954

git bisect says #39564 is to blame. /cc @michalvavrik

Expected behavior

No such warnings (as in 3.9.0 and before)

Actual behavior

Warnings since 3.9.1

How to Reproduce?

No response

Output of uname -a or ver

No response

Output of java -version

17.0.11

Quarkus version or git rev

3.9.4

Build tool (ie. output of mvnw --version or gradlew --version)

Maven 3.9.6

Additional information

The respective Maven module doesn't have any sources, but it has dependencies to almost all other modules in the repo.
Interestingly, another module in the repo (which builds a different "flavor" of the app) doesn't have this issue, but it also has fewer dependencies (but it does contain some sources).

@famod famod added the kind/bug Something isn't working label Apr 19, 2024
@quarkus-bot
Copy link

quarkus-bot bot commented Apr 19, 2024

/cc @FroMage (resteasy-reactive), @geoand (resteasy-reactive), @stuartwdouglas (resteasy-reactive)

@famod
Copy link
Member Author

famod commented Apr 19, 2024

@vavr I wanted to link @michalvavrik instead. I've correct that, sorry for the ping.

@gsmet
Copy link
Member

gsmet commented Apr 19, 2024

Any chance we could have a small reproducer? (You knew it was coming!)

@michalvavrik
Copy link
Member

michalvavrik commented Apr 19, 2024

Algorithm used in #39564 have to handle field class types that can have various subclasses and so on. I was thinking that we could just give up on detection in some classes if it will be too much (make them included to security serializer implicitly). However then I added a caching of this detection so I didn't think it was necessary.

Problem is that sometimes you can even have endpoint returning Object and I think if actual class returned from the endpoint is class with secured field, it should be secured as well. The case with Object we can simplify, but there can be others like this. That's why it is complex detection. If you provide a reproducer, I'd like to dig in.

@gsmet
Copy link
Member

gsmet commented Apr 19, 2024

Do we really want to index additional classes though? For me if the class is not in the Jandex index, I would expect things to get ignored (similarly to JAX-RS resources will be ignored)

I'm a bit worried about the Object case you mention, what do you do in this case? You scan the whole classpath looking for potential @SecureField?

@michalvavrik
Copy link
Member

Do we really want to index additional classes though? For me if the class is not in the Jandex index, I would expect things to get ignored (similarly to JAX-RS resources will be ignored)

I am sorry, I don't know indexes as well. IIRC I just used index that was already used for it, I just changed detection algorithm.

I'm a bit worried about the Object case you mention, what do you do in this case? You scan the whole classpath looking for potential @SecureField?

The algorithm that is in place must be able to detect that SomeType has a subtype with a field that is secured. For the Object itself I think condition can be vastly simplified: when there is at least one annotation instance with SecureField and Object is detected, answer is always that SecureField has been detected for that endpoint. Sadly I didn't think about that before. If it is really the Object (which we are just guessing) that fix is easy. I'll simplify it anyway now that I know about that.

@gsmet
Copy link
Member

gsmet commented Apr 19, 2024

I haven't digged too much but I wonder if things shouldn't be done the opposite way i.e. scan the index for secure fields and determine the set of interfaces/classes that could be impacted.

That way we would scan the index only once.
Typically, I'm a bit worried about how well the current approach would scale when you have a lot of endpoints.

@michalvavrik
Copy link
Member

I haven't digged too much but I wonder if things shouldn't be done the opposite way i.e. scan the index for secure fields and determine the set of interfaces/classes that could be impacted.

If I detect field annotated with SecureField on the class that's superclass is a field class of the class that is implementation of the interface returned from the endpoint, then I don't think we can go from that annotation instance. Is it supported by Jandex, please? It sounds really good, but I didn't find such an option.

That way we would scan the index only once.
Typically, I'm a bit worried about how well the current approach would scale when you have a lot of endpoints.

My understanding is that if I keep in hashmap "scanned" types, than I don't do it twice and that map is kept for all the endpoints. If this should affect build time or memory recognizably, then it needs to by fixed.

cc @geoand

I tried to improve the algorithm to detect more cases, this algorithm is not perfect because it can be very complex with generics, wildcards etc.

@gsmet
Copy link
Member

gsmet commented Apr 19, 2024

Yeah so first you would have to find classes with @SecuredField.

Then you would have to get a list of all classes potentially impacted by this. Interfaces/superclasses/subclasses of the class are easy.
I'm not entirely sure how easy it would be to get the occurrences in other classes.

Jandex has a IndexView#getKnownUsers() method that maybe is what we want. But I think you should clarify first what you actually want to look at and also why exactly are you trying to detect the @SecureField so broadly?
I don't have much context tbh.

Once we have clarified what we want to do, we can discuss with @Ladicek what our options with Jandex are.

@michalvavrik
Copy link
Member

michalvavrik commented Apr 19, 2024

Yeah so first you would have to find classes with @SecuredField.

Then you would have to get a list of all classes potentially impacted by this. Interfaces/superclasses/subclasses of the class are easy. I'm not entirely sure how easy it would be to get the occurrences in other classes.

Jandex has a IndexView#getKnownUsers() method that maybe is what we want.

annotation instance -> field type -> getKnownUsers and recursion up to the object until we find what can be an endpoint can work. Fields annotated with SecureField can be String and int and so on. I cannot tell if such algorithm is really better for the performance. However if you are convinced or there is an issue with the algorithm in place, I am happy to try it.

But I think you should clarify first what you actually want to look at and also why exactly are you trying to detect the @SecureField so broadly? I don't have much context tbh.

I was fixing #39513 and I thought it would be lame to just fix one case out of many. Right now behavior of the SecureField is not based on documented definition (in other words - I did not find documented definition to follow), so I believe it was better to improve it, but users must always test it. I can't tell what is expected behavior. @geoand can define it and then, we can alter if there is an issue with current behavior.

Once we have clarified what we want to do, we can discuss with @Ladicek what our options with Jandex are.

Alright, thank you.

@Ladicek
Copy link
Contributor

Ladicek commented Apr 19, 2024

I'm not sure if I understand the issue correctly, but I don't think a single scan over the index will ever be enough. Regardless of whether you start with the types that can be returned, or with the types that have a @SecureField annotation, you will always have to iterate until nothing new is found (or you reach a defined limit).

I don't know what would be the best course of action here, but I think it would be good to filter out some fields (such as static fields or @JsonIgnore fields) early on. That should have a decent chance of getting rid of these warnings.

@michalvavrik
Copy link
Member

michalvavrik commented Apr 29, 2024

Hello,

I don't want to forget about this, @famod is there a chance that you can provide a reproducer without too much of a work? Now I have mentioned that keycloak/keycloak#28947 exists so I think I can try to use the Keycloak project. I'll try it later this week.

I'm not convinced that approach suggested by @gsmet is more performant due to how many usages primitive data types will have. I'll try @Ladicek suggestion first and see what the results are.

Thanks

@gsmet
Copy link
Member

gsmet commented Apr 29, 2024

Fields annotated with SecureField can be String and int and so on.

Not sure how this related to what I wrote. You don't care about the type of the field but the type of the enclosing class AFAIU.

Now apparently getKnownUser() doesn't work in the case of fields. @Ladicek can you confirm this?

@michalvavrik
Copy link
Member

Fields annotated with SecureField can be String and int and so on.

Not sure how this related to what I wrote. You don't care about the type of the field but the type of the enclosing class AFAIU.

Now apparently getKnownUser() doesn't work in the case of fields. @Ladicek can you confirm this?

The way I understood your suggestion is to lookup annotation instances, check field type and get known users. Sure, if it will start working with fields, it's better solution.

@Ladicek
Copy link
Contributor

Ladicek commented Apr 29, 2024

Now apparently getKnownUser() doesn't work in the case of fields. @Ladicek can you confirm this?

No, it's a lot worse :-) The getKnownUsers() method only considers a class as used in another class when it occurs in the list of class references in the other class's constant pool. This PR smallrye/jandex#354 should improve it.

@gsmet
Copy link
Member

gsmet commented Apr 29, 2024

The way I understood your suggestion is to lookup annotation instances, check field type and get known users. Sure, if it will start working with fields, it's better solution.

Oh so there was a misunderstanding. For me, you start at the field but get the users of the enclosing class (to start building a tree of how it is used).
FWIW, I had a similar requirement for the config work we were doing with Roberto (but with methods return type) so I think we should probably have a way to determine the list of paths leading to a specific type/field/method.

@michalvavrik
Copy link
Member

Oh so there was a misunderstanding. For me, you start at the field but get the users of the enclosing class (to start building a tree of how it is used).
FWIW, I had a similar requirement for the config work we were doing with Roberto (but with methods return type) so I think we should probably have a way to determine the list of paths leading to a specific type/field/method.

Sounds good @gsmet , indeed that's better. Thanks. IIUC it will require @Ladicek PR.

I'll think about temporary fixes till then when I debug this with the Keycloak reproducer.

@gsmet
Copy link
Member

gsmet commented Apr 29, 2024

Now, as mentioned by @Ladicek, we might have to apply the same exclusions we apply to when we index ReflectiveHierarchy. IIRC we have a specific exclusion for JAX-RS return types already which might be slightly related to what you're doing.

@michalvavrik
Copy link
Member

michalvavrik commented May 3, 2024

Alright, thanks for all the help. I've opened #40448 and also detected case that didn't work (#40447). Tested it with Keycloak project on main branch (running quarkus/server in dev mode after switch from resteasy-reactive to quarkus-rest) and this fixes their issue.

We can follow-up when Jandex gets planned improvements.

@quarkus-bot quarkus-bot bot added this to the 3.11 - main milestone May 10, 2024
@gsmet gsmet modified the milestones: 3.11 - main, 3.10.1 May 10, 2024
@famod
Copy link
Member Author

famod commented May 15, 2024

Fix confirmed in 3.10.1, thanks!

PS: Sorry for the lack of feedback, I've been on PTO for over two weeks.

@michalvavrik
Copy link
Member

Fix confirmed in 3.10.1, thanks!

PS: Sorry for the lack of feedback, I've been on PTO for over two weeks.

np, thank you for the confirmation

@woprandi
Copy link

I got these warnings on 3.8.4 (with latest Keycloak) so I'm surprised about the title

@michalvavrik
Copy link
Member

I got these warnings on 3.8.4 (with latest Keycloak) so I'm surprised about the title

Hey @woprandi , I agree it is not a straighforward, but 3.9.1 was released on March 27 and 3.8.4 on April 17, therefore it makes sense users first experienced it in 3.9.1.

@woprandi
Copy link

@michalvavrik Ok I see thanks

@gsmet
Copy link
Member

gsmet commented May 16, 2024

@famod can you test with 3.10.1 and make sure things work properly for you?

@famod
Copy link
Member Author

famod commented May 16, 2024

@gsmet

@famod can you test with 3.10.1 and make sure things work properly for you?

That's what I was trying to say with

Fix confirmed in 3.10.1

Meaning with 3.10.1 I don't see those warnings anymore and haven't spotted any regressions thus far.

@mabartos
Copy link
Contributor

Typically, I'm a bit worried about how well the current approach would scale when you have a lot of endpoints.

If this should affect build time or memory recognizably, then it needs to be fixed.

@michalvavrik @gsmet The scalability is not very good, I'd say. After merging this PR #39564, the augmentation time significantly increased for the Keycloak project. Please see keycloak/keycloak#29579.

The situation for a "plain" Keycloak might be kinda acceptable, but we support extending the Keycloak functionality by adding custom providers (JARs) for handling custom REST endpoints, and it's much worse.

As seen in keycloak/keycloak#29579, the augmentation time for the build step increased from ~17ms to ~800ms without any additional JARs. With the provided JARs, it increased from ~20ms to ~44500ms.

@cwelch-rh might provide more information on this.

@cwelch-rh Might be good to create a separate issue for this.

@michalvavrik
Copy link
Member

michalvavrik commented May 21, 2024

@mabartos I expect after #40448 times for Keycloak itself are better than they were even before #39564. That is situation has improved against previous state now. Can you give it a try with Quarkus 3.10.1, please?

As seen in keycloak/keycloak#29579, the augmentation time for the build step increased from ~17ms to ~800ms without any additional JARs. With the provided JARs, it increased from ~20ms to ~44500ms.

The keycloak/keycloak#29579 steps to reproduce says The increase in time can be seen without providers, but it's more dramatic with ours.. I don't know how to add providers. It would be interesting for me to experiment with these horrific numbers against 3.8.4 as I would add my custom secure fields, but I would need more specific steps to reproduce, probably added to the KC issue.

@michalvavrik
Copy link
Member

@Ladicek I read https://smallrye.io/blog/jandex-3-2-0/ Index.getKnownUsers() passage and I have one question, is a class considered as a user of another class when the parent class or interface of the other class is present in any of its members, please?

@Ladicek
Copy link
Contributor

Ladicek commented May 21, 2024

@michalvavrik No, the class will only be considered as a user of the parent class.

@michalvavrik
Copy link
Member

@michalvavrik No, the class will only be considered as a user of the parent class.

thank you

@gsmet
Copy link
Member

gsmet commented May 21, 2024

@mabartos @cwelch-rh any chance we could have some profiling data? We provide some information about how to profile using asyncprofiler here: https://github.com/quarkusio/quarkus/blob/main/TROUBLESHOOTING.md .

Also, yes, please create a new issue.

@gsmet
Copy link
Member

gsmet commented May 21, 2024

And I agree with @michalvavrik that it would be interesting to have a datapoint with 3.10.1. We might have to backport the subsequent patch to 3.8 if it improves things for you significantly.

@gsmet
Copy link
Member

gsmet commented May 22, 2024

@mabartos @cwelch-rh if you want fixes to be included in the next 3.8, we will need to move fast. So could you have a look at the comments above ^? Thanks!

@gsmet gsmet modified the milestones: 3.10.1, 3.8.5 May 22, 2024
@cwelch-rh
Copy link

I was able to test with 3.10.1, the augmentation time looks good to me. These times are about what we expect.

With providers:

[io.qua.dep.QuarkusAugmentor] (main) Quarkus augmentation completed in 8742ms

Without:

[io.qua.dep.QuarkusAugmentor] (main) Quarkus augmentation completed in 6092ms

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/rest kind/bug Something isn't working
Projects
None yet
7 participants