both are for dependency injection. `inject()` is f...
# tornadofx
a
both are for dependency injection.
inject()
is for singleton components (
Models()
,
Views()
,
Controllers()
) which is TornadoFX specific. For
di()
, you can inject third party resources by creating an
FX.dicontainer
c
Yes, I've figured all of this out, question is why have two injection mechanisms when one would've done the trick. E.g. Ratpack framework also has its own injection mechanism, but it is implemented as an API and when you plug Spring IoC or Guice internal mechanism is just substituted. Exactly like
by di()
works, but in tornadofx we have two APIs.
a
I can't answer for @edvin but maybe it's just that you have a lot less work to do if it's a TornadoFX feature as opposed to a 3rd party mechanism
e
Now that 2.0 is around the corner, we might want to investigate swithing out the built in
inject()
for an abstraction which would support other mechanisms as well, but still provide a default implementation.
a
So we'd be possibly interested in finding a way to consolidate the mechanisms? Would that include making less work for 3rd party mechanisms?
c
@amanda.hinchman-dominguez Actually current setup for a 3rdparty mechanism seems trivial enough, do you have any suggestions? This is how I've enabled SpringFu:
Copy code
internal val koFu = application {
	//SpringFu config
}

class MyAppUi : App(LoginScreen::class) {
	override fun init() {
		koFu
			//init SpringFu context
			.run()
			.also { applicationContext ->
				FX.dicontainer = object : DIContainer {
					override fun <T : Any> getInstance(type: KClass<T>): T =
						applicationContext.getBean(type.java)

					override fun <T : Any> getInstance(type: KClass<T>, name: String): T =
						applicationContext.getBean(name, type.java)
				}
			}
	}
}
this snippet is basically teaching TFX how to use external DI by just overriding two methods that are more or less universally provided by other containers. Only way to simplify this configuration, I think, would be to provide declarative integration for most popular DI frameworks out of the box, but I do not really think that necessary. It could look something like this in case of SpringFu:
Copy code
internal val koFu = application {
	//SpringFu config
}

class MyAppUi : App(LoginScreen::class) {
	override fun init() {
		koFu
			//init SpringFu context
			.run()
			.also(FX::useSpringContext)
	}
}
Hm... looks better, maybe we should, after all there are not too many popular DI containers out there.
e
The current mechanism is trivial enough, and it would be even nicer if we actually supplied default implementations for the most popular containers. Just add the tornadofx-spring dependency for example, and you're set. I seem to remember some instances where the di mechanism falls short, because you can't easily glean much information about the injection point. We should look at adding an InjectionPoint class as a parameter instead of just the type perhaps.
πŸ‘ 3
a
Hmmm.... So, according to the source code, using
inject()
right now can only use the types that are
Injectable
which is extended by
ScopedInstance
. My question for injecting 3rd party beans is "how often will we ever need to override getInstances other than by type or
id
?" Perhaps you're right @Czar, it would be worth providing at least a refactor to simplify the code for creating a DI container for popular di frameworks like say, Spring, SpringFu, Dagger
e
Yes, there is a specific divide between inject and di right now. Consolidating them seems like a good idea. I remember I tried but stopped for some reason, can't remember what it was. Looking at it now though, I'm sure we would be able to combine them.
c
Huh, nice! I could help with contributing Spring/SpringFu integration when you have the design ready.
a
@edvin @Czar I finished my work for my talk and burned out on THAT research, so I'm wanting catching up on work I wanted to do for TornadoFX, I'm a bit manual in checkin my thinking - we already have examples provided by the both of you for Spring/Spring Fu. I can submit a ticket tonight to implement a refactored version but I'd also be interested in trying to see if Dagger would end up being the same concept
e
Oh, sweet @Czar πŸ™‚
a
I can start on that when I get home tonight but for now, I can submit an issue so we can brainstorm!
e
Most of these injection frameworks are based on similar ideas, but we should definitely look at a bunch of them to make sure we can cater for them all
a
@carlw has done some work with dependency injection as well, from Google Guice and aspectJ as well, but I think this was originally with JavaFX
those are the main ones off the top of my head
e
Yeah, if we have these, I think we'll be pretty well covered. The nice thing about adding an InjectionPoint class is that it could be extended later on without breaking backwards compatibility.
a
@edvin turns out, you have an example of Google Guice as well covered in issue #79 and it also looks the same. I'll add these examples in the new ticket!
c
Is
InjectionPoint
something that exists in TFX already, or is it a new idea?
πŸ‘ 1
e
That's a new idea πŸ™‚
πŸ‘ 1
Something similar is used in other frameworks, like JavaEE
We could pass in the type and the injection point could be optional.
So, implement the one you need πŸ™‚
a
Thanks for the clarification on that, I was thinking man I haven't spotted that before hahaha
e
Great. Annotations is one of those things that needs to be exposed
a
@Czar what's your username on github
c
it's
AlexCzar
e
Thanks Amanda πŸ™‚
a
Not sure how to add folks, but here it is: https://github.com/edvin/tornadofx/issues/909
I'll take a look at this tonight!
e
Great! I think it will be pretty straight forward. The only issue is that TornadoFX has some lifecycle callbacks that need to be taken care of. It's all (or at least mostly) encapsulated within the current
find
implementation.
a
oh, interesting, I didn't realize that the lifecycle would affect dependency injection. I'll take a look at that part to see what you mean
e
Great πŸ™‚
c
I took a look at Spring's and CDI's `InjectionPoint`s, it looks like this feature is only applicable to scope
prototype
(Spring) and
dependent
(CDI) beans, which makes sense if you think about it. CDI will actually even throw an exception if you try to use it on anything but
dependent
, Spring took a weird route of giving you the first encountered point instead.
a
should we just try to keep it at the beans only for spring?
e
I think what we need is to expose the owning class as well as the requested type, plus any annotations on the injected field.
c
From what I understand currently, we only need to expose it in case our bean/component is scoped (in the sense that it is available in several TFX scopes), otherwise for us too IP should either throw or at least warn the user that its use is meaningless.
e
It wouldn't be meaningless if the user added additional annotations to the injection field, would it?
c
what if you inject it into two different classes?
e
Not sure I see the issue. In fact, that's when we'd need the information about the surrounding class and any field annotations
Sorry if I'm not following here πŸ™‚
c
Let me whip up an example... sec.
a
^ would be helpful. I'm of the mind to just write this feature for simple beans and beans with ids and still leave the option to create Fx.dicontainers for more complicated stuff
c
Copy code
class MyController: Controller()

class View1 {
  @AnnotationOne
  val myController: MyController by inject()
}

class View2 {
  @AnnotationTwo
  val myController: MyController by inject()
}
MyController
is a singleton and it is injected into two different views, which specify two different annotations, which annotation should be taken into account during
MyController
instantiation?
a
Dumb question - why would you want them under 2 different annotations in this case?
Mind you this is the burnout talking
e
For each request to inject, it would look at the annotations. Maybe the annotation would mean a different scope, or some other feature defined in the injection framework. I do see your point though.
For Injectable subclasses that wouldn't make much sense, but for 3rd party beans it might
c
Then it'll have semantics different than its counterparts in JEE/Spring. I don't know if it's a bad thing or a good thing though. @amanda.hinchman-dominguez people are unpredictable πŸ˜„ That is to say, I have no idea why.
a
Thanks for the clarification here. In Dagger 2, what you end up doing is providing a Qualifier to for your Provides type to differentiate, so I suppose this is could be a similar situation in Dagger 2
@Czar no this is a situation that totally makes sense! We may want to include in the feature the ability for qualifiers in say, Spring and Dagger then. I don't know about the other ones specifically.
c
Qualifiers are somewhat different animals, they are used to narrow down which bean you want if several are available otherwise.
e
That's right
c
Injection point on the other hand is used to create different kind of a bean
πŸ‘ 1
e
It wouldn't be very practical to use annotations on a TornadoFX resource, but it might for 3rd party beans
a
mmmmmm.... yikes. Okay. @Czar maybe this is something we can add on then after we define what the preliminary work looks like? Let's start with the simplest acceptable cases and build as appropriate. We still wanted to have these exist as dependencies, right?
c
Yup, and in that case it needs to align with the existing architectures, that is qualifier - to narrow down if type is not enough, injection point to customize creation, when bean is specified as a prototype/dependent/using a factory
with tfx, qualifier is effectively string passed to find/inject, so we already have that. we just need to add InjectionPoint, to make the analogy complete and make Spring/JEE (and possibly others) happy πŸ™‚
e
Yes, exactly. So TornadoFX's default injection mechanism would simply ignore annotations, but pass them on to any third party system configured. If that system can't make sense of the annotations or the injection point, it would throw an exception, right?
c
I'm not sure throwing an exception is a good idea, intuition tells me there could be use cases, e.g. maybe during mocking/tests when throwing exception will not be desirable.
we need a bit more research I believe
e
Introducing this in the RC for 2.0 might be a good idea to give people a chance to play with it before it is set in stone as well
c
It's almost 23:30 for me, so I have to bid you farewell for now, but tomorrow after work I'll see how Spring's IP can be integrated into existing di() mechanism and hopefully will have more understanding and stuff to present.
e
Great. Have a good night πŸ™‚
πŸ™‡β€β™‚οΈ 1
a
sounds good. When I get home tonight I'll try to put up some messy code for at least a baseline, see what you guys think
πŸ‘ 1
I pushed up an initial idea and added a comment to the ticket about some thoughts about this: https://github.com/edvin/tornadofx/pull/910
Grocery delivery was canceled, I have to run out and get them before it record lows hit Chicago πŸ™ƒ
e
@amanda.hinchman-dominguez What's the temp in Chicago? We had about -18 celcius here today πŸ™‚
a
it's not bad today but I'm working from home tomorrow. It's really the Great Lakes and the wind that's killing us
winds are roughly 35km/h
e
@amanda.hinchman-dominguez -14F is pretty cold πŸ™‚ We don't even get that low every year, but around -4F is pretty normal here in jan/feb
Ah, then it feels a lot colder!
a
oh no, that's -14C haha it's only 6F
it's bearable today
tomorrow will be -14 or -18F
e
Haha, OK! That's shorts and t-shirt weather! hehe
πŸ˜„ 1
We have a guy at work who wears sandals and shorts all year round. Yesterday he wore shoes for the first time in ages because we've had a lot of snow the last couple of days
a
I'm a Floridian and I think 70F is cold - at this point, it's just "cold" and "really freaking cold"
πŸ˜‚ 1
e
70F is summer in Norway.. haha
a
Bless his soul, I have a friend Mumbai who did the same hahaha
e
Well, we'd get up to 90F for a few weeks
a
My ideal temperature. This whole business with plants dying and people dying if their cars break down is a JOKE
e
90F is good as long as I have air condition! If not, it's unbearable torture... hehe
c
I miss Norway, beautiful, beautiful country πŸ™‚ I don't mind the cold, prices on the other hand... πŸ˜„
When I was visiting someone gave me a key chain pendant which had "This is the only thing I could afford in Norway" written on it πŸ˜„
a
hahahaha damn, is it more expensive than Chicago?
c
No idea, I haven't been to Π‘hicago πŸ™‚ But a pint of average beer in pubs in Trondheim for example was about $12-$15
e
@Czar Haha, yeah Norway is quite expensive, but salaries are also high, so it's not so bad for natives. Fun for us to visit other countries though πŸ˜†
Americans would probably choke on our fuel prices. Those are brutal. Up to $8 per gallon.
c
Yeah, but you are getting rid of gas powered vehicles in the nearest future anyway πŸ™‚
It's probably a combination of pre-existing housing, social benefits and salary that makes it comfortable for locals, I was doing my math on the offers I get from time to time from Norway and Sweden, and in the end it is always a noticeable financial downgrade for me in terms of net earnings.
a
Oh wow - here that's how much mixed drinks cost in my neighborhood. Beer is more like $7. As for gas, america depends on it so much they would probably riot. I wouldn't be surprised if it happens the way things have been going here. People are acting like asking for a $15 minimum wage is a lot but we've been asking for 10 years now. $8 is simply not a livable wage and social benefits have continued to get cut nonstop
@Czar did you get a chance to look at potential ideas for implementation with that feature request?
no rush on it or anything, the next 2 days are a bit of scrap for me since Windy City Dev Fest is tomorrow
c
@amanda.hinchman-dominguez Not really, I've played around a bit with Spring's
InjectionPoint
, but haven't had much time to engage otherwise. Doesn't look like I'll be able to before the weekend.
a
same! cool cool just wanted to pop in and check πŸ˜„
πŸ™‚ 1