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

Running into issues with SpringComponentFinderStrategy tripping over multiple interface hits #103

Closed
deinspanjer opened this issue Aug 9, 2018 · 3 comments

Comments

@deinspanjer
Copy link

deinspanjer commented Aug 9, 2018

Working with this strategy:

        new ComponentFinder(
            attackPath, "com.example.svc",
            new SpringComponentFinderStrategy(
                new ReferencedTypesSupportingTypesStrategy()
            ),
            new SourceCodeComponentFinderStrategy(
                sourceRoots.get("example-svc").toFile(),
                150
            )
        ).findComponents();

As it is running through the classes, it comes across one that looks like this:

@Component
public class SomethingUpdateDbConsumer implements Consumer<List<Some>> {

The AbstractSpringComponentFinderStrategy.findInterfacesForImplementationClassesWithAnnotation() method sees the interface java.util.function.Consumer and decides that this component should be represented as that.

However, a few loop iterations later, it finds this guy:

@Component
public class OtherthingUpdateDbConsumer implements Consumer<List<Other>> {

And going through the same logic as before, tries to add a second component named Consumer which blows up.

At the top of the loop, there is a check for whether the candidate component already exists in the components, but it is checking on the simple name, not the interface name, so it doesn't see a problem, and there isn't a check whether this interface name already exists prior to trying to insert it.

So.. a few questions:

  1. I don't really want these guys to be represented by something as abstract and unrelated to my architecture as java.lang.function.Consumer. However, I haven't yet found a nice way to be able to blacklist the interface or tell the strategy to stop looking at interfaces at all. What to do?
  2. In the case of my actual classes like *RepositoryImpl, they aren't getting de-interfaced because the interface they implement is something called *RepositoryExtras which extends from an interface called *Repository which extends from org.springframework.data.repository.CrudRepository. Bleh. It doesn't look like this AbstractSpringComponentFinderStrategy tries to do any recursive interpretation of interfaces, should I just write off trying to use the SpringComponentFinderStrategy entirely because my code base is too "fancy" for it?
@simonbrowndotje
Copy link
Contributor

simonbrowndotje commented Aug 9, 2018

  1. I will need to check this, but since the component finders are working on bytecode, and because of (generics) erasure, this might be the reason why both the SomethingUpdateDbConsumer and OtherthingUpdateDbConsumer are being identified as the same Consumer component.

  2. The pre-built Spring component finder only has some relatively simple rules for identifying components and their interfaces, based upon the typical naming and coding conventions. With your repositories, the component finder strategy is only looking for interfaces that are assignable to CrudRepository, which will be why your implementation classes are being ignored.

For both issues, you may be better off either (1) writing your own component finder strategy, which implements the rules based upon how your codebase is structured or (2) use a different set of strategies based upon naming conventions, etc. This perhaps isn't the answer that you wanted, but FWIW, this is exactly why the client library is open source ... every codebase is structured differently, and the rules for identifying components in one codebase are usually different to others.

Hope that helps.

@deinspanjer
Copy link
Author

Wow, thanks for the lightning response.

I'm not upset by that answer in the slightest. I definitely figured my issues around the repository stuff were going to necessitate a custom finder strategy. Yay open source!

I was thinking that it might be useful for the built in spring component finder to avoid trying to use interfaces that have nothing to do with spring components. Do you see any merit in that?

@deinspanjer
Copy link
Author

deinspanjer commented Sep 12, 2018

I ended up creating an almost clone of SpringComponentComponentFinderStrategy that just added the following check right before it tests for an interface:

// We don't really want to name things after generic internals such as java.util.function.Consumer
if (interfaceType.getCanonicalName().startsWith("java.")) {
    continue;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants