Coder Social home page Coder Social logo

beanpuree's Introduction

BeanPurée

BeanPurée is a middle layer between JavaBeans and shapeless.

NOTE: The library is in active development stage. So the API might be changed.

Build Status Join the chat at https://gitter.im/limansky/beanpuree codecov Maven Central

Motivation

Even though Scala is compatible with Java, the languages are different, and the coding styles are different too. In Scala we prefer to use immutable case classes, but in Java world mutable JavaBeans are common building blocks. Moreover, many Scala libraries provide API which requires case classes (e.g. different serializers). As result, we need to have similar model classes for Java and Scala. This library helps to convert data between JavaBeans and case classes.

Usage

BeanPurée is available for Scala 2.10, 2.11, 2.12, and 2.13.0-M2. Currently there is no release version. Adding in sbt:

libraryDependencies += "me.limansky" %% "beanpuree" % "0.3"

If you'd like to use development version:

resolvers += Resolver.sonatypeRepo("snapshots")

libraryDependencies += "me.limansky" %% "beanpuree" % "0.4-SNAPSHOT"

The core of BeanPurée is BeanGeneric class, which have a same role with shapeless Generic, but for JavaBeans. Assume we have class:

public class Foo {
    private int a;
    private String b;

    public int getA() { return a; }
    public void setA(int a) { this.a = a; }

    public String getB() { return b; }
    public void setB(String b) { this.b = b; }

    public String toString() {
        return "Foo(" + a + ", \"" + b + "\")";
    }
}

Now we can create BeanGeneric instance and convert bean to HList and backward:

scala> val gen = BeanGeneric[Foo]
gen: me.limansky.beanpuree.BeanGeneric[Foo]{type Repr = shapeless.::[Int,shapeless.::[String,shapeless.HNil]]}

scala> val foo = gen.from(5 :: "aaa" :: HNil)
foo: Foo = Foo(5, "aaa")

scala> foo.setB("changed")

scala> gen.to(foo)
res2: gen.Repr = 5 :: changed :: HNil

Another important thing is LabelledBeanGeneric, which is a LabelledGeneric adopted for the beans. It's important to note, that it uses "field names" generated from the getters names. E.g. getStartTime become startTime and isEven become even.

JavaTypeMapper[J, S] provides converters for different Java and Scala classes. There are converter instances from Java numeric classes to corresponding Scala ones. It also can convert nullable value to Option. You can convert HLists of convertable values as well.

scala> type JavaType = Integer :: String :: java.lang.Long :: HNil
defined type alias JavaType

scala> type ScalaType = Int :: String :: Option[Long] :: HNil
defined type alias ScalaType

scala> val m = JavaTypeMapper[JavaType, ScalaType]
m: me.limansky.beanpuree.JavaTypeMapper[JavaType,ScalaType] = me.limansky.beanpuree.JavaTypeMapper$$anon$1@41bbc4c4

scala> m.javaToScala(6 :: "test" :: null :: HNil)
res0: ScalaType = 6 :: test :: None :: HNil

scala> m.scalaToJava(42 :: null :: Some(66l) :: HNil)
res1: JavaType = 42 :: null :: 66 :: HNil

The next thing is a BeanConverter and StrictBeanConverter classes. They use LabelledBeanGeneric and LabelledGeneric to convert between beans and case classes.

scala> case class Bar(a: Int, b: String)
defined class Bar

scala> val conv = BeanConverter[Foo, Bar]
conv: me.limansky.beanpuree.BeanConverter[Foo,Bar] = me.limansky.beanpuree.BeanConverter$$anon$1@4eae0bc5

scala> conv.beanToProduct(foo)
res3: Bar = Bar(5,changed)

scala> conv.productToBean(Bar(15, "bar"))
res4: Foo = Foo(15, "bar")

The converters doesn't care about fields order. The difference between these two classes is that StrictBeanConverter requires the same fields of converting classes having the same types. It means that if the bean uses Java numeric classes (like java.lang.Integer), the case class also should have the field with Java class.

BeanConverter is more intelligent. It uses JavaTypeMapper to convert field types. You should be careful using it. For example if you have an Integer field in Java class and Int in Scala, you might get a NullPointerException if the value is null. Use Option[Int] to make it safe.

beanpuree's People

Contributors

atry avatar gitter-badger avatar limansky avatar

Stargazers

 avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.