Open aghasemi opened 5 years ago
You can try to start your investigation with check if LabelledBeanGeneric
instance can be found for your class. And if LabelledGeneric
is defined for your case class.
Thanks. Seems the issue is with the bean (LabelledBeanGeneric). Is there any criteria bean classes should meet? In my case, the class implements Serializable and fields are protected (instead of private), yet everything else is a typical bean.
Two other suspicions:
Further tracking down, it seems the problem is the Align class. Any criteria here?
Hm... As I remember Align
is using only in StrictBeanConverter
. Anyway there no limitations in Align
or AlignByKey
itself.
If I were you I would try to comment out pairs of getters and setters one by one to find the problem one.
Similar issue.
I'm using "me.limansky" %% "beanpuree" % "0.4"
And for the following test:
package example
import org.scalatest._
import me.limansky.beanpuree._
import me.limansky.beanpuree.BeanConverter
import me.limansky.beanpuree.BeanConverter._
import scala.beans.BeanProperty
class Foo(@BeanProperty var a:Int, @BeanProperty var b: String) {override def toString = s"$a:$b"}
case class Bar(a: Int, b: String) {override def toString = s"$a:$b"}
class ConvTest extends WordSpecLike with Matchers {
"Suite" should {
"compare" in {
val p = Bar(1,"a")
val b = new Foo(1,"a")
p.a shouldEqual b.getA
p.b shouldEqual b.getB
}
"convert" in {
val p = Bar(1,"a")
val conv = BeanConverter[Foo, Bar]
val b = conv.productToBean(p)
p.a shouldEqual b.getA
p.b shouldEqual b.getB
}
}
}
produces error:
beanpuree\CmdParserTest.scala:25:31: could not find implicit value for parameter sbc: me.limansky.beanpuree.BeanConverter[example.Foo,example.Bar]
[error] val conv = BeanConverter[Foo, Bar]
[error] ^
[error] one error found
[error] (Test / compileIncremental) Compilation failed
When I comment out convert
, Suite gets passed.
What is wrong?
Hi @vtitov
I've never tried to use beans created as a Scala classes with BeanProperty annotations. It looks like there is some difference between these classes and real Java beans. I'll investigate that. Thanks for isolating problem.
I've found that's wrong with your class: it doesn't have default constructor. Thus, it's not a JavaBean by definition: https://en.wikipedia.org/wiki/JavaBeans
They are serializable, have a zero-argument constructor, and allow access to properties using getter and setter methods.
If you change it:
scala> class Foo(@BeanProperty var a:Int, @BeanProperty var b: String) {override def toString = s"$a:$b"; def this() = this(0, "") }
defined class Foo
scala> val gen = BeanGeneric[Foo]
gen: me.limansky.beanpuree.BeanGeneric[Foo]{type Repr = Int :: String :: shapeless.HNil} = $anon$1@8ff9b6f
scala> gen.from(1 :: "aaa" :: HNil)
res2: Foo = 1:aaa
The reason of this behavior is that BeanGeneric
(or LabelledBeanGeneric
) uses the default constructor to create object from HList. In case of your class the generated code will be like:
val gen = new BeanGeneric[Foo] {
override type Repr = Int :: String :: HNil
override def to(foo: Foo): Repr = foo.getA :: foo.getB :: HNil
override def from(repr: Repr) = repr match {
case a :: b :: HNil =>
val foo = new Foo()
foo.setA(a)
foo.setB(b)
foo
}
}
@aghasemi is it the same issue you have?
@vtitov Is this kind of classes are really used in your projects? I think it's possible to support it, if it really required.
Mike,
No, it were not real classes. I faced similar problem while attempting to use beanpuree from pure Java. I try to use scala adapter object as a workaround.
@vtitov Could you provide problem Java class?
@limansky, the issue was somewhat different:
...ConvTest.scala:15:46: could not find implicit value for parameter sbc: > me.limansky.beanpuree.BeanConverter[B,P] [error] @BeanProperty val converter = BeanConverter[B, P] [error] ^ [error] one error found
scala helper
class JavaBeanConverterHelper[B,P] {
@BeanProperty val converter = BeanConverter[B, P]
}
java converter
package example;
import me.limansky.beanpuree.*;
public class JavaBeanConverter<B, P> {
private BeanConverter<B, P> converter = new JavaBeanConverterHelper<B, P>().getConverter();
public B productToBean(P p) { return converter.productToBean(p); }
public P beanToProduct(B b) { return converter.beanToProduct(b); }
}
testcase
"convert-java" in {
val p = Bar(1,"a")
val conv = new JavaBeanConverter[Foo, Bar]
val b = conv.productToBean(p)
p.a shouldEqual b.getA
p.b shouldEqual b.getB
}
Hi, Intellij (and Maven) cannot, somehow, find the required implicits when I define a BeanConverter. I have imported me.limansky.beanpuree._. Any idea how I can debug this?