How do integrate scala into guice ?

689 views
Skip to first unread message

meconsea

unread,
Dec 19, 2008, 12:03:40 AM12/19/08
to google-guice
Hi All:

I' ve been working on a project for a new client, I do
thinking integrate scala into guice, and I have integrated guice into
warp-persist. The struts2 has been used for the UI of project.
I'm hoping to the scala that is using in the project.

How do integrate scala into guice?

TIA for any pointers!


francisco treacy

unread,
Dec 19, 2008, 3:28:51 AM12/19/08
to google...@googlegroups.com
yesterday i came across an article about DI and scala, guice is
mentioned towards the bottom of the post:
http://jonasboner.com/2008/10/06/real-world-scala-dependency-injection-di/

francisco

Jan Kriesten

unread,
Dec 20, 2008, 4:51:56 AM12/20/08
to google...@googlegroups.com

Hi,

> How do integrate scala into guice?
> TIA for any pointers!

Guice integrates with Scala almost as seamlessly as Java. There are some corner
cases, but nothing which can't be worked around.

I use Guice on a regular basis with Scala and Wicket. Works great for me.

Best regards, --- Jan.

meconsea

unread,
Dec 21, 2008, 8:22:12 PM12/21/08
to google-guice
To: Jan Kriesten

Can you give me a demo that about integrate scala into guice?

Thanks!

Jan Kriesten

unread,
Dec 22, 2008, 6:27:41 AM12/22/08
to google...@googlegroups.com

> 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.


Ryan Leach

unread,
Jul 6, 2015, 3:56:35 AM7/6/15
to google...@googlegroups.com, krie...@mail.footprint.de
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?

Nate Bauernfeind

unread,
Jul 6, 2015, 7:31:30 AM7/6/15
to google...@googlegroups.com, krie...@mail.footprint.de
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:

Thanks,
Nate

--
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 google-guice...@googlegroups.com.
To post to this group, send email to google...@googlegroups.com.
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.
For more options, visit https://groups.google.com/d/optout.

Ryan Leach

unread,
Jul 6, 2015, 2:21:21 PM7/6/15
to google...@googlegroups.com, krie...@mail.footprint.de
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()

Nate Bauernfeind

unread,
Jul 6, 2015, 2:36:23 PM7/6/15
to google...@googlegroups.com, krie...@mail.footprint.de
This sounds, possibly, like a good use case for a child injector.

I can't seem to find the wiki article on them, but I saw some stackoverflow URLs pop up and the API has a decent javadoc:

Reply all
Reply to author
Forward
0 new messages