Kotlin inner class as Spring Bean

被刻印的时光 ゝ 提交于 2021-01-29 07:41:06

问题


I used Kotlin with Spring boot and i met some errors about bean creation.

error message was Index 0 out of bounds for length 0 in spring framework class

i dont understand why caused exception about this java code(spring)

for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
  Class<?> paramType = paramTypes[paramIndex];
  String paramName = (paramNames != null ? paramNames[paramIndex] : ""); // Here!           
  ...
}

is that possible?

anyway, i want to know how create spring bean as kotlin inner class with property values(@ConfigurationProperties).

my code


// application.yml
naver:
  clientId: ...
  clientSecret: ...
  grantType: authorization_code
  redirectUri: ...
  accessTokenUrl: ...
  profileUrl: ...

// some codes
abstract class OAuth2Provider {
  lateinit var clientId: String
  lateinit var clientSecret: String
  lateinit var grantType: String
  lateinit var redirectUri: String
  lateinit var accessTokenUri: String
  lateinit var profileUri: String

  fun callback(code: String) = getProfiles(getAuthenticationResult(code))
  abstract fun getAuthenticationResult(code: String): AuthenticationResult
  abstract fun getProfiles(result: AuthenticationResult): Map<String, String>
}

@Component
class Providers(
  val restTemplate: RestTemplate
) {

  private fun createOauth2LoginParams(grantType: String, clientId: String, code: String): MultiValueMap<String, String> {
    val map = LinkedMultiValueMap<String, String>()
    map.add("grant_type", grantType)
    map.add("client_id", clientId)
    map.add("code", code)
    return map
  }

  private fun createOauth2HttpEntity(map: MultiValueMap<String, String>): HttpEntity<MultiValueMap<String, String>> {
    val headers = HttpHeaders()
    headers.contentType = APPLICATION_FORM_URLENCODED
    return HttpEntity(map, headers)
  }

  private fun createAuthenticationResult(url: String, entity: HttpEntity<MultiValueMap<String, String>>): AuthenticationResult {
    return restTemplate.postForObject(url, entity, AuthenticationResult::class.java)!!
  }

  private fun createProfileResponseEntity(url: String, result: AuthenticationResult): ResponseEntity<Map<*, *>> {
    val headers = HttpHeaders()
    headers.add("Authorization", result.tokenType + " " + result.accessToken)
    headers.contentType = MediaType.APPLICATION_FORM_URLENCODED

    val entity = HttpEntity<MultiValueMap<String, String>>(headers)
    return restTemplate.exchange(url, HttpMethod.GET, entity, Map::class.java)
  }

  @ConfigurationProperties("naver")
  @Component
  inner class Naver : OAuth2Provider() {

    override fun getAuthenticationResult(code: String): AuthenticationResult {
      val map = createOauth2LoginParams(grantType, clientId, code)
      map.add("client_secret", clientSecret);

      val entity = createOauth2HttpEntity(map)
      return createAuthenticationResult(accessTokenUri, entity)
    }

    override fun getProfiles(result: AuthenticationResult): Map<String, String> {
      val resultEntity = createProfileResponseEntity(profileUri, result)
      val body = resultEntity.body!!

      val uniqueId = body.get("id").toString()
      val imageUrl = body.get("profile_image").toString()

      val profiles = HashMap<String, String>()
      profiles["uniqueId"] = uniqueId
      profiles["imageUrl"] = imageUrl
      return profiles
    }
  }

}

errors

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.mubeeplayer.api.oauth2.Providers$Naver': Unexpected exception during bean creation; nested exception is java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
...
Caused by: java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:705) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:218) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1341) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1187) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515) ~[spring-beans-5.1.7.RELEASE.jar:5.1.7.RELEASE]

Thank you. sorry for my english.


回答1:


This seems to be a spring framework issue.

The root cause has been explained to be with:

MethodParameter L:781

if (function != null) { 
    List<KParameter> parameters = function.getParameters(); 
    KParameter parameter = parameters
        .stream()
        .filter(p -> KParameter.Kind.VALUE.equals(p.getKind()))
        .collect(Collectors.toList()) 
        .get(index); 
        return (parameter.getType().isMarkedNullable() || parameter.isOptional()); 
}

When checking for required constructor parameters in DependencyDescriptor the statement above filters out Parameter 0 which is a reference to the outer class and has kind value of INSTANCE.

It then attempts to access the parameter based on the initial input index, but the stream has been filtered down to empty.

Edit

Nested classes are however supported and work as expected. A nested class is a class defined inside a class having no modifier in kotlin and static modifier in java. An inner class on the other hand is a class defined inside a class having inner modifier in kotlin and no modifier in java.



来源:https://stackoverflow.com/questions/56306227/kotlin-inner-class-as-spring-bean

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!