I have the following class
class MigrateJob #Inject()(
val resultsMetadataRepo: ResultsMetadataRepo,
val resultsMetadataDao: ResultsMetadataDao,
val tenantProvisioningDao: TenantProvisioningDao,
val migrationOffsetDao: MigrationOffsetDao) extends Job {
def startULFMigrationJob(tenantId: String): Unit = {}
}
To test this MigrateJob class i have this in the test. Whats the syntax for boot strap initialization i am not able to follow and did not find working samples either.
#Test def launchWorkflow(): Unit = {
var guiceBundle =
GuiceBundle.newBuilder[SchedulerApiConfiguration].
addModule(new SchedulerModule)
.enableAutoConfig(getClass.getPackage.getName)
.setConfigClass(classOf[SchedulerApiConfiguration]).build
guiceBundle.initialize(new Bootstrap[SchedulerApiConfiguration](new SchedulerApiConfiguration()))
val injector = guiceBundle.getInjector
val migrateToULFJob = new MigrateToULFJob(
injector.getInstance(classOf[ResultsMetadataRepo]),
injector.getInstance(classOf[ResultsMetadataDao]),
injector.getInstance(classOf[TenantProvisioningDao]),
injector.getInstance(classOf[MigrationOffsetDao]))
migrateToULFJob.startULFMigrationJob(tenantId)
I have 2 controllers in my Spring boot application: RestControllerA returns JSON using snake_case, and RestController2 returns JSON using camelCase.
Is there a way to easily configure this? I'm currently doing something ugly like this:
#RestController
class RestControllerA(
#Qualifier("objectMapperSnakeCase")
private val objectMapperSnakeCase: ObjectMapper <-- I shouldn't have to inject this in.
) {
#GetMapping("/test-endpoint-1")
fun endpoint1(): ResponseEntity<String> { <-- I shouldn't have to return a string.
val employee = Employee(...)
val jsonString = objectMapperSnakeCase.writeValueAsString(employee)
return ResponseEntity.ok().body(jsonString)
}
}
#RestController
class RestControllerB(
#Qualifier("objectMapperCamelCase")
private val objectMapperCamelCase: ObjectMapper <-- I shouldn't have to inject this in.
) {
#GetMapping("/test-endpoint-2")
fun endpoint2(): ResponseEntity<String> { <-- I shouldn't have to return a string.
val employee = Employee(...)
val jsonString = objectMapperCamelCase.writeValueAsString(employee)
return ResponseEntity.ok().body(jsonString)
}
}
What I would prefer:
#RestController
class RestControllerA {
#GetMapping("/test-endpoint-1")
#ObjectMapperToUse("objectMapperSnakeCase") <-- Nice and easy.
fun endpoint1(): Employee {
return Employee(...)
}
}
// Similar for RestControllerB with objectMapperCamelCase
For the following Kotlin class:
class ProductLogic(
private val product: Product?
) {
fun shouldShow(): Boolean {
if (product == null) {
return false
}
val version = product.version!!
if (!Utils.isAtLeastVersionX(version.major, version.minor)) {
return false
}
return true
}
}
I am trying to write a parameterized test in Kotlin:
#RunWith(ParameterizedRobolectricTestRunner::class)
#Config(constants = BuildConfig::class, sdk = [19], packageName = "com.example")
class ProductLogicTest(
private val product: Product?,
private val shouldShow: Boolean
) {
#Before
fun setUp() {
// doReturn(VERSION).`when`(product).version // (2) Raises a NotAMockException
}
#Test
fun shouldShow() {
assertThat(ProductLogic(product).shouldShow(), `is`(shouldShow))
}
companion object {
#JvmStatic
#Parameters(name = "{index}: {0} => {1}")
fun data(): Collection<Array<Any?>> {
val productMock = mock<Product>(Product::class.java)
doReturn(VERSION).`when`(productMock).version // (1) Is not applied
return asList(
arrayOf(productMock, false),
// ...
)
}
}
I want to parameterize the value of the Product#version property. When I (1) modify its value in the data() function it is not applied when running test. When I (2) try to modify its value in #Before a NotAMockException is raised:
org.mockito.exceptions.misusing.NotAMockException:
Argument passed to when() is not a mock!
Example of correct stubbing:
doThrow(new RuntimeException()).when(mock).someMethod();
Please note that the example is simplified - the real ProductLogic class consists of more parameters which rectify to using a parameterized test.
Robolectric and Mockito versions:
testImplementation 'org.robolectric:robolectric:4.1'
testImplementation 'org.mockito:mockito-core:2.23.4'
Also, to mock final classes, I created file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker with content:
mock-maker-inline
Classes to test:
class ProductLogic(private val product: Product?) {
fun shouldShow(): Boolean {
if (product == null) {
return false
}
val version = product.version
return !isAtLeastVersionX(version.minor, version.major)
}
private fun isAtLeastVersionX(minor: Int, major: Int): Boolean {
val v = 5
return v in minor..major
}
}
class Product(val version: Version)
class Version(val minor: Int, val major: Int)
Next test code works for me and test is passed:
import org.hamcrest.CoreMatchers.`is`
import org.junit.Assert.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.mock
import org.robolectric.ParameterizedRobolectricTestRunner
import org.robolectric.annotation.Config
import java.util.Arrays.asList
#RunWith(ParameterizedRobolectricTestRunner::class)
#Config(sdk = [19], packageName = "com.example")
class ProductLogicTest(private val product: Product,
private val shouldShow: Boolean) {
#Before
fun setUp() {
//doReturn(VERSION).`when`(product).version // if uncomment works fine
}
#Test
fun shouldShow() {
assertThat(ProductLogic(product).shouldShow(), `is`(shouldShow))
}
companion object {
private val VERSION = Version(1, 5)
#JvmStatic
#ParameterizedRobolectricTestRunner.Parameters(name = "{index}: {0} => {1}")
fun data(): Collection<Array<Any?>> {
val productMock = mock(Product::class.java)
doReturn(VERSION).`when`(productMock).version // Works fine
return asList(
arrayOf(productMock, false)
)
}
}
}
So I am extremely new to Scala and seem to be doing something horribly wrong for a simple logic.
I need to query database to get all the WebsiteTemplates.
I am then trying to access the first element of the sequence (simply for practice) but keep getting the ClassCastException - [Ljava.lang.Object; cannot be cast to models.WebsiteTemplate. Next, I would want to return the entire Seq obtained as Json. Tried Json.arr() but won't work. Searched but none matches the exact use case strangely. Here is relevant the code -
WebsiteController
#Singleton
class WebsiteTemplateController #Inject()(websiteTemplateDAO: WebsiteTemplateDAO, db: DB) extends Controller{
def index = Action.async {
implicit request => db.withTransaction() {
implicit em => {
try {
val templates: Seq[WebsiteTemplate] = websiteTemplateDAO.findAll()
val template = templates(0)
Logger.info("The size is " + template.name)
Future(Ok(Json.obj(
"message" -> "Success"
)))
} catch {
case e: Exception =>
e.printStackTrace()
Future(InternalServerError(s"Lag gaye"))
}
}
}
}
}
WebsiteDAOImpl
#ImplementedBy(classOf[WebsiteTemplateDAOImpl])
trait WebsiteTemplateDAO extends DAO[WebsiteTemplate]{
def findAll()(implicit em: EntityManager): Seq[WebsiteTemplate]
}
#Singleton
class WebsiteTemplateDAOImpl #Inject()(db: DB) extends DAOImpl(classOf[WebsiteTemplate]) with WebsiteTemplateDAO{
override def findAll()(implicit em: EntityManager): Seq[WebsiteTemplate] = {
val query = em.createQuery(s"SELECT idint, name FROM WebsiteTemplate")
db.executeQuery(query)
}
}
DAOImpl
trait DAO[T] {
def findById(id:String)(implicit em:EntityManager) : Option[T]
def create : T
}
class DAOImpl[T](cls:Class[T]) extends DAO[T] {
def findById(id: String)(implicit em: EntityManager): Option[T] = {
val query = em.createQuery(s"Select c from ${cls.getName} as c where c.id=:id")
query.setParameter("id",id)
val list = query.getResultList
if (list.nonEmpty) {
Option(list(0).asInstanceOf[T])
} else {
None
}
}
override def create: T = {
cls.newInstance()
}
}
WebsiteTemplate
#Entity
#Table(name = "templates")
#EntityListeners(Array(classOf[SetForeignKeyOnSave]))
class WebsiteTemplate{
#Id
#Column(name = "id")
#BeanProperty
var intid: java.lang.Integer = _
/*#Transient
override var id: String = _*/
#BeanProperty
#Column(name = "name")
var name: String = _
}
A bit more explanation of my problem. On getting the type of templates(0) using getClass() method, it shows as [Ljava.lang.Object whereas I expect it to be of type WebsiteTemplate.
Is there an easy way to serialize to json without "tpe" field inside an object?
I need to serialize case classes to json structures and then, send them over the wire (They won't been deserialized in future). I have a specific api, so.. I don't need additional fields.
For class Person illustrated below:
case class Person(Name: String, Age: int, CandyLover: Boolean)
I'd like to see following:
{
"Name": "Paul",
"Age": 23,
"CandyLover": true
}
I would suggest you to take a look at spray-json or argonaut. Or play-json if you are already using Play.
Scala pickling is not really a json library, it was not created to generate JSON for public API, it's not flexible, you can't define JSON protocol first and then provide pickling serialization to match protocol. Pickling is for computer-to-computer serialization where no one is really care about bytes going between apps.
Probably the simplest way to do it is to pass somehow the Hint into JSONPickleBuilder. Quick way to do it is to override builders in JSONPickleFormat by calling hintStaticallyElidedType() method from PickleTools.
Here is kind of code snippet to demonstrate it:
import org.specs2.matcher.JsonMatchers
import org.specs2.mutable.Specification
import org.specs2.specification.Scope
import scala.pickling.Defaults._
import scala.pickling.json.{JSONPickleBuilder, JSONPickleFormat, JsonFormats}
import scala.pickling.{Output, PBuilder, PickleTools, StringOutput}
class PersonJsonFormatsTest extends Specification with JsonMatchers {
trait Context extends Scope with PersonJsonFormats
trait PersonJsonFormats extends JsonFormats {
override implicit val pickleFormat: JSONPickleFormat = new PersonJSONPickleFormat
}
class PersonJSONPickleFormat extends JSONPickleFormat {
override def createBuilder() = new JSONPickleBuilder(this, new StringOutput) with PickleTools {
hintStaticallyElidedType()
}
override def createBuilder(out: Output[String]): PBuilder = new JSONPickleBuilder(this, out) with PickleTools {
hintStaticallyElidedType()
}
}
"Pickle" should {
"Serialize Person without $type field in resulting JSON" in new Context {
case class Person(Name: String, Age: Int, CandyLover: Boolean)
val pickledPersonObject = Person("Paul", 23, CandyLover = true).pickle
println(pickledPersonObject.value)
pickledPersonObject.value must not */("$type" → ".*".r)
}
}
}
The output of println(pickledPersonObject.value) will be as you need:
{
"Name": "Paul",
"Age": 23,
"CandyLover": true
}
This way you will stay aligned with further pickle updates.
P.S. If someone knows more elegant and convenient way to reach the same behaviour - please let us know :-)
For scala-pickling 0.10.x:
import scala.pickling._
import scala.pickling.json.{JSONPickle, JSONPickleBuilder, JSONPickleFormat, JsonFormats}
import scala.pickling.pickler.AllPicklers
object serialization extends JsonFormats with Ops with AllPicklers {
override implicit val pickleFormat: JSONPickleFormat = new JSONPickleFormat {
private def setHints(h: Hintable): Unit = {
h.hintStaticallyElidedType()
h.hintDynamicallyElidedType()
}
override def createBuilder(): JSONPickleBuilder = {
val builder = super.createBuilder()
setHints(builder)
builder
}
override def createBuilder(out: Output[String]): PBuilder = {
val builder = super.createBuilder(out)
setHints(builder)
builder
}
override def createReader(pickle: JSONPickle): PReader = {
val reader = super.createReader(pickle)
setHints(reader)
reader
}
}
}
object SerializationTest extends App {
import serialization._
case class Person(firstName: String, lastName: String)
val pickle: JSONPickle = Person("Evelyn", "Patterson").pickle
val jsonString: String = pickle.value // {"firstName": "Evelyn","lastName": "Patterson"}
val person: Person = jsonString.unpickle[Person]
}
For scala-pickling 0.11.x:
import scala.pickling._
import scala.pickling.json.{JSONPickle, JSONPickleBuilder, JSONPickleFormat}
import scala.pickling.pickler.AllPicklers
object serialization extends AllPicklers {
private final class CustomJSONPickleFormat(tag: FastTypeTag[_]) extends JSONPickleFormat {
private def setHints(h: Hintable) {
h.hintElidedType(tag)
}
override def createBuilder(): JSONPickleBuilder = {
val b = super.createBuilder()
setHints(b)
b
}
override def createBuilder(out: Output[String]): PBuilder = {
val b = super.createBuilder(out)
setHints(b)
b
}
override def createReader(pickle: JSONPickle): PReader = {
val b = super.createReader(pickle)
setHints(b)
b
}
}
implicit val staticOnly = static.StaticOnly // for compile time serialization methods generation
implicit final class EncodeDecodeOps[T](picklee: T) {
def encode(implicit pickler: Pickler[T]): String = {
val pickleFormat = new CustomJSONPickleFormat(pickler.tag)
functions.pickle(picklee)(pickleFormat, pickler).value
}
def decode[A](implicit c: T => String, unpickler: Unpickler[A]): A = {
val pickleFormat = new CustomJSONPickleFormat(unpickler.tag)
functions.unpickle[A](json.JSONPickle(picklee))(unpickler, pickleFormat)
}
}
}
case class Person(firstName: String, lastName: String) {
#transient var x = "test"
}
object SerializationTest extends App {
import serialization._
val jsonString = Person("Lisa", "Daniels").encode
println(jsonString)
val person = jsonString.decode[Person]
println(person)
}