Uploaded image for project: 'Wicket'
  1. Wicket
  2. WICKET-7086

Injecting Spring bean may cause ClassCastException

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Minor
    • Resolution: Fixed
    • 9.15.0
    • 10.0.0, 9.17.0
    • wicket-spring
    • None

    Description

      Issue Summary:

      The getBeanNameOfClass() method used for injecting Spring beans into Wicket components has a limitation when dealing with generic collection fields. The method is designed to look up a bean name based on the raw type of the collection (e.g., List). However, in scenarios where there are beans with more specific generic types (e.g., List<SomeClass>), the method incorrectly resolves and injects the bean, leading to potential ClassCastException issues at runtime.

      Problem Details:

      When the field class is a generic collection (e.g., List<AnyClass>), the getBeanNameOfClass() method resolves a bean with the type of the raw collection (e.g., List). This behavior generally works as intended. However, when there are beans with more specific generic types (e.g., List<SomeClass>), the method incorrectly identifies and injects the bean, even if the generic types (SomeClass and AnyClass) do not match. This results in unexpected behavior and may cause ClassCastException errors later in the application.

      Reproduction Scenario:

      This issue becomes apparent when using Apache Causeway in conjunction with Spring Data REST.  There is a bean named defaultMessageConverters (wich is a List) is inserted into CausewayWicketApplication within the applicationInitializers field, it is erroneously resolved based on the raw type, leading to improper injection.

      Proposed Solution:

      Review and enhance the getBeanNameOfClass() method to consider generic types more accurately, ensuring that beans are resolved based on compatibility with the field's specific generic type. 

      Problem is here:

       

      List<String> names = new ArrayList<>(
          Arrays.asList(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(ctx, clazz)));
       

       

      It uses the clazz, without generic.

      Possible solution:

       

      ResolvableType resolvableType = generic != null ? ResolvableType.forClassWithGenerics(clazz, generic) : ResolvableType.forClass(clazz);
      List<String> names = new ArrayList<>(
          Arrays.asList(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(ctx, resolvableType)));
       

       

      It is compatible with Spring from 4.2. 

       

      Additional Context:

      This problem affects scenarios where generic collections are used in Spring-Wicket integration, and it becomes particularly prominent when Apache Causeway is utilized alongside Spring Data REST.

       

      Attachments

        1. repro.tgz
          64 kB
          Miklós Győrfi

        Issue Links

          Activity

            People

              mgrigorov Martin Tzvetanov Grigorov
              gyorfimi Miklós Győrfi
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: