Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

does not bind AnyVal properly... #49

Open
shengc opened this issue Aug 27, 2015 · 6 comments
Open

does not bind AnyVal properly... #49

shengc opened this issue Aug 27, 2015 · 6 comments

Comments

@shengc
Copy link

shengc commented Aug 27, 2015

This throws java.lang.reflect.MalformedParameterizedTypeException. I think the problem is Guice depends on Java reflection which cannot properly interpret AnyVal, as I cannot assign null to the initial value of Foo in BarProvider, since Foo is not bounded by Null

class Foo(val foo: String) extends AnyVal {}
object Foo {
  def apply(foo: String): Foo = new Foo(foo)

  def empty: Foo = new Foo("")
}

import com.google.inject._
import net.codingwell.scalaguice._

class BarProvider extends Provider[String] {
  @Inject val foo: Foo = Foo.empty

  def get() = foo.toString()
}

class Module extends AbstractModule with ScalaModule {
  def configure() {
    bind[Foo].toInstance(Foo("abc"))
    bind[String].toProvider[BarProvider]
  }
}

import net.codingwell.scalaguice.InjectorExtensions._

val injector = Guice.createInjector(new Module)
Console.println(injector.instance[String])
@nbauernfeind
Copy link
Member

By the way, I think you want this implementation of get (which injects the wrapped string foo and not Foo.toString()):

class BarProvider extends Provider[String] {
  @Inject val foo: Foo = Foo.empty

  def get() = foo.foo
}

If you're looking to allow your Foo.empty to be Foo(null) then you need to mark the injection as null-safe. In that case try this:

import javax.annotation.Nullable

class BarProvider extends Provider[String] {
  @Inject @Nullable val foo: Foo = Foo.empty

  def get() = foo.foo
}

@nbauernfeind
Copy link
Member

Or possibly you wanted to do this?

@Inject @Nullable val foo: Foo = null.asInstanceOf[Foo]

I can't seem to reproduce the specific error that you're getting. Is there a specific version of guice/jvm/scala that you're using?

@nbauernfeind
Copy link
Member

Actually, I can't seem to get guice to inject the Foo inside of the BarProvider. So yeah, it doesn't seem like I can inject an AnyVal at all.

@shengc
Copy link
Author

shengc commented Aug 27, 2015

@nbauernfeind that is really weird ! It does not throw exception now. However as I change BarProvider to spit out Foo.foo instead, the program always prints empty string instead of abc. Is that what happens at your end ?

@shengc
Copy link
Author

shengc commented Aug 27, 2015

Unless this is an sbt bug, this snippet has a totally messed up error ...

case class A()
case class B()

class Foo[A, B](val foo: String) extends AnyVal {}
object Foo {
  def apply(foo: String): Foo[A, B] = {
    Console.println("h")
   new Foo(foo) 
  }

  def empty: Foo[A, B] = new Foo("")
}

import com.google.inject._
import com.google.inject.name._
import net.codingwell.scalaguice._

class BarProvider extends Provider[String] {
  @Inject @Named("f") val foo: Foo[A, B] = Foo.empty

  def get() = foo.foo
}

class M extends AbstractModule with ScalaModule {
  def configure() {
    bind[Foo[A, B]].annotatedWithName("f").toInstance(Foo("abc"))
    bind[String].toProvider[BarProvider]
  }
}

import net.codingwell.scalaguice.InjectorExtensions._

val injector = Guice.createInjector(new M)
Console.println(injector.instance[String]

error:

1) No implementation for java.lang.String annotated with     @com.google.inject.name.Named(value=f) was bound.
  while locating java.lang.String annotated with @com.google.inject.name.Named(value=f)
    for field at BarProvider.foo(<console>:25)
 at M.bind(<console>:30)

@shengc
Copy link
Author

shengc commented Aug 28, 2015

A minimized example showing the problem.

  import com.google.inject._
  import com.google.inject.name._
  import net.codingwell.scalaguice._

  class Foo(val foo: String) extends AnyVal

  class Bar @Inject() (foo: Foo) {
    override def toString() = foo.foo
  }

  object TestModule extends AbstractModule with ScalaModule {
    def configure() {
      bind[Foo].toInstance(new Foo("abc"))
      bind[Bar]
    }
  }

  import net.codingwell.scalaguice.InjectorExtensions._

  val injector = Guice.createInjector(TestModule)

  Console.println("bar = " + injector.instance[Bar].toString())
  Console.println("foo = " + injector.instance[Foo].foo

output:

[info] bar =
[info] foo = abc

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants