Thankyou for the concern about the anti-pattern but in the API there are
producers that create objects from factories that I'm going to add soon,
maybe as a submodule that will require the instances.
If I could use the parent projects injector for the other classes I would,
but since I can't (it only injects into the main application class) I'm
using this as a workaround and recreating the injector. Ideally I would be
able to get the parent project to inject the sub-classes but it isn't
exposed.
I ended up solving the problem by changing the module to a variable in the
ServiceInjector that gets set from the main application when it receives a
construction event, before the injector is used then made the injector lazy.
I'm not sure I like this solution but it works for now.
@Plugin(id = "au.id.rleach.overmind", name = "Overmind", version =
"0.0.1-SNAPSHOT")
final class OvermindPlugin {
@Inject
private val game: Game = null
@Inject
private val logger: Logger = null
@Inject
private val pluginManager: PluginManager = null
@Inject
private val serviceManager: ServiceManager = null
@Inject
private val eventManager: EventManager = null
@Inject
private val gameRegistry: GameRegistry = null
@Inject
private val teleportHelper: TeleportHelper = null
@Subscribe def onConstruction(event: ConstructionEvent): Unit = {
logger debug "Plugin constructed"
ServiceInjector.module = new OModule(this, game, logger, pluginManager,
serviceManager, eventManager, gameRegistry, teleportHelper)
val x = new TestListener with Listener with ServiceInjector
x.init()
}
}
class OModule(val plugin: Object, val game: Game, val logger: Logger, val
pluginManager: PluginManager, val serviceManager: ServiceManager, val
eventManager: EventManager, val gameRegistry: GameRegistry, val teleportHelper:
TeleportHelper) extends Module {
override def configure(binder: Binder): Unit = {
binder.bind(classOf[Game]).toInstance(game)
binder.bind(classOf[Logger]).toInstance(logger)
binder.bind(classOf[PluginManager]).toInstance(pluginManager)
binder.bind(classOf[ServiceManager]).toInstance(serviceManager)
binder.bind(classOf[EventManager]).toInstance(eventManager)
binder.bind(classOf[GameRegistry]).toInstance(gameRegistry)
binder.bind(classOf[TeleportHelper]).toInstance(teleportHelper)
binder.bind(classOf[Object]).toInstance(plugin)
binder.bind(classOf[Object]).annotatedWith(Names.named(plugin.getClass.getAnnotation(classOf[Plugin]).id())).toInstance(plugin);
//bind(classOf[File]).annotatedWith(new
ConfigDirAnnotation(true)).toInstance(Loader.instance.getConfigDir)
}
}
/**
* Marker class to mark that the class will not function correctly unless
initialized after injection/construction.
*/
trait Initializable {
/**
* Must be run after a class is injected to get the class ready to use
*/
def init() : Unit
}
trait ServiceInjector {
ServiceInjector.inject(this)
}
object ServiceInjector {
var module : Module = null
private lazy val injector = Guice.createInjector(
module
)
def inject(obj: Initializable) = {
injector.injectMembers(obj)
obj.init()
}
def inject(obj: AnyRef) = {
injector.injectMembers(obj)
}
}
On Monday, July 6, 2015 at 9:01:30 PM UTC+9:30, Nate Bauernfeind wrote:
>
> In general this is an anti-pattern in Guice. If you have to pass instances
> of every object in your graph to the guice module constructors then you're
> not using Guice for any injection at all. What does your java version of
> this use-case look like? It seems that you did not translate it to Scala
> correctly.
>
> Guice works in Scala just like it works in Java. There is a wonderful
> project which introduces the right amount of syntactic sugar to make your
> life easier in Scala, but fundamentally it's all the same.
>
> Take a look at this project and let me know if you still have Scala
> specific questions:
> https://github.com/codingwell/scala-guice
>
> Thanks,
> Nate
>
> On Mon, Jul 6, 2015 at 3:56 AM Ryan Leach <[email protected]
> <javascript:>> wrote:
>
>> First up sorry to reply to such an old post, but it appears pretty high
>> in search when I look for the problem, so figured anyone else finding it
>> would appreciate an answer if they found the same post.
>>
>> I'm very new to Scala and trying to work out how I can use the previous
>> pattern for dependency injection, when the Guice Module itself needs
>> references to instances passed in from elsewhere.
>>
>> But since traits can't have constructors, and neither can the Companion
>> Object it looks like I'm screwed?
>>
>> package au.id.rleach.overmind.guice
>>
>> import com.google.inject.{Provides, Guice, Binder, Module}
>> import org.slf4j.Logger
>> import org.spongepowered.api.service.ServiceManager
>> import org.spongepowered.api.world.TeleportHelper
>> import org.spongepowered.api.{GameRegistry, Game}
>> import org.spongepowered.api.plugin.PluginManager
>> import org.spongepowered.api.scoreboard.ScoreboardBuilder
>> import org.spongepowered.api.service.event.EventManager
>>
>> class OModule(val game: Game, val logger: Logger, val pluginManager:
>> PluginManager, val serviceManager: ServiceManager, val eventManager:
>> EventManager, val gameRegistry: GameRegistry, val teleportHelper:
>> TeleportHelper) extends Module {
>>
>> override def configure(binder: Binder): Unit = {
>> binder.bind(classOf[Game]).toInstance(game)
>> binder.bind(classOf[Logger]).toInstance(logger)
>> binder.bind(classOf[PluginManager]).toInstance(pluginManager)
>> binder.bind(classOf[ServiceManager]).toInstance(serviceManager)
>> binder.bind(classOf[EventManager]).toInstance(eventManager)
>> binder.bind(classOf[GameRegistry]).toInstance(gameRegistry)
>> binder.bind(classOf[TeleportHelper]).toInstance(teleportHelper)
>> //bind(classOf[File]).annotatedWith(new
>> ConfigDirAnnotation(true)).toInstance(Loader.instance.getConfigDir)
>> }
>> }
>>
>> trait ServiceInjector {
>> ServiceInjector.inject(this)
>> }
>>
>> object ServiceInjector {
>> private val injector = Guice.createInjector(
>> //####
>> new OModule()//compilation error.
>> //####
>> )
>> def inject(obj: AnyRef) = injector.injectMembers(obj)
>> }
>>
>> I realize that the object is being initialized when the class is loaded,
>> and that is before I even have a copy of the instance to pass to OModule,
>> so it seems the whole advice is flawed?
>>
>> On Monday, December 22, 2008 at 9:57:41 PM UTC+10:30, Jan Kriesten wrote:
>>>
>>>
>>> > Can you give me a demo that about integrate scala into guice?
>>>
>>> Well, it's actually almost as referred to you in the link from the other
>>> answer:
>>>
>>>
>>> http://jonasboner.com/2008/10/06/real-world-scala-dependency-injection-di/
>>>
>>> class MyClient {
>>> @Inject val toBeInjected: AnotherClass = toBeInjected // !!
>>> }
>>>
>>> trait ServiceInjector {
>>> ServiceInjector.inject( this )
>>> }
>>>
>>> object ServiceInjector {
>>> private val injector = Guice.createInjector( Array[Module]( new
>>> YourModule ) )
>>> def inject( obj: AnyRef ) = injector.injectMembers( obj )
>>> }
>>>
>>> Usage:
>>>
>>> val client = new MyClient with ServiceInjector
>>>
>>> or:
>>>
>>> class InjectedMyClient extends MyClient with ServiceInjector
>>>
>>> Best regards, --- Jan.
>>>
>>>
>>> --
>> You received this message because you are subscribed to the Google Groups
>> "google-guice" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected] <javascript:>.
>> To post to this group, send email to [email protected]
>> <javascript:>.
>> Visit this group at http://groups.google.com/group/google-guice.
>> To view this discussion on the web visit
>> https://groups.google.com/d/msgid/google-guice/0b5c01b0-ad63-4a37-916e-6b00c7ceaa8c%40googlegroups.com
>>
>> <https://groups.google.com/d/msgid/google-guice/0b5c01b0-ad63-4a37-916e-6b00c7ceaa8c%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>> For more options, visit https://groups.google.com/d/optout.
>>
>
--
You received this message because you are subscribed to the Google Groups
"google-guice" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/google-guice.
To view this discussion on the web visit
https://groups.google.com/d/msgid/google-guice/5009b55d-52cf-4ba8-ba4f-34fe23f9590d%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.