https://kotlinlang.org logo
#spring
Title
# spring
j

Jon Senchyna

03/17/2023, 2:59 PM
Hey folks, I'm trying to register a Kotlin top-level
object
as a bean in Spring and am wondering if there's a simpler way to do this. Why I'm doing this is a long story. What I've tried so far: 1. Annotate my object with
@Component
(results in Spring creating a second instance of my object) 2. Create a separate
@Configuration
class and expose my object as an
@Bean
in a method in there.
Here's what the second one looks like:
Copy code
object MyObject : SomeDependencyInterface {
  // ...
}

@Configuration
class RegisterMyObject {
  @Bean
  fun myObject() = MyObject
}
Ultimately, I'm wondering if there's a way to ditch the
@Configuration
class and just register my object as a
@Component
.
s

Sam

03/17/2023, 3:20 PM
Your solution #2 doesn’t look too bad. I expect you could write a custom scope for singleton objects, but it would end up being more code. But I think it’s worth revisiting the “why”, even if it is a long story 😄. It’s possible there’s a simpler solution.
d

Davio

03/17/2023, 3:28 PM
This makes no sense, if it is an object, there is no need to turn it into a bean because you can call all of the functions itside it directly without needing an instance
a

ashmelev

03/17/2023, 3:30 PM
I agree with @Davio - you are doing the same thing twice (hence the two instances)
j

Jon Senchyna

03/17/2023, 4:10 PM
I completely agree. This issue is that the thing that needs a bean is in a separate library and doesn't know about this object.
#2 is fine, it's not a huge amount of extra code and does the job. I was just seeing if there was a way to make it even simpler so that if this gets replicated to other projects, there's less boilerplate in those cases.
The reason it's an object is to be able to call all of the stuff inside it (a bunch of constants and nested constants in child objects). The reason it's a bean is that it implements an interface that registers said constants with an external service. It's part of a feature flag system. The same class is used to tell the external "Feature Flag service" which flags exist and to also give the internal code a simple API to access said flags.
v

vbsteven

03/17/2023, 4:24 PM
If the object is inside your library and implements the public interface, then the fact that it is an object is an implementation detail of your library and should not be exposed to the outside world. So option 2 with the additional
@Configuration
class seems the most sensible, but I would modify it slightly and add the interface as an explicit return type of the bean method so the actual object can be private/internal
Copy code
private object MyObject : SomeDependencyInterface {
  // ...
}

@Configuration
class RegisterMyObject {
  @Bean
  fun myObject(): SomeDependencyInterface = MyObject
}
Ofcourse this also means that anywhere you want to inject this object, will need to inject based on
SomeDependencyInterface
and not
MyObject
.
j

Jon Senchyna

03/17/2023, 5:18 PM
Yep, that's basically what I'm doing at this point. Valid point on the explicit type for the bean. Appreciate the suggestions.
u

Umit AYDIN

03/18/2023, 9:37 AM
Spring does have scope configuration for beans if this is something you are looking for https://www.baeldung.com/spring-bean-scopes
18 Views