StackOverflowError when using JsonSerializer with Gson and Scala - scala

I'm trying to use Gson and Scala in a simple test. This is working fine when printing the author instance, where I'm receiving a json representation of the author. However, when replacing it with the book instance, I'm getting a StackOverflowError. I read in other places that this might happen if there is a circular reference between the classes, but I can't see it here. I'm attaching the code and part of the error stack below and am thankful for any suggestions as to how to solve this problem.
Code:
import com.google.gson._
import java.lang.reflect.Type
import scala.collection.mutable._
object GsonTest extends App {
val gsonBuilder = new GsonBuilder
gsonBuilder.registerTypeAdapter(classOf[Author], new AuthorSerializer)
gsonBuilder.registerTypeAdapter(classOf[Book], new BookSerializer)
val book = Book("test book")
val author = Author("test author")
book.authors += author
val gson = new Gson
println(gson.toJson(author))
println(gson.toJson(book))
}
case class Author(name: String)
case class Book(name: String) {
val authors = MutableList[Author]()
}
class AuthorSerializer extends JsonSerializer[Author] {
override def serialize(src: Author, typeOfSrc: Type, context: JsonSerializationContext) = {
val json = new JsonObject
json.addProperty("name", src.name)
json
}
}
class BookSerializer extends JsonSerializer[Book] {
override def serialize(src: Book, typeOfSrc: Type, context: JsonSerializationContext) = {
val json = new JsonObject
json.addProperty("name", src.name)
val jsonAuthorArray = new JsonArray
for (author <- src.authors) {
jsonAuthorArray.add(context.serialize(author))
}
json.add("authors", jsonAuthorArray)
json
}
}
Error stack:
Exception in thread "main" java.lang.StackOverflowError
at com.google.gson.reflect.TypeToken.equals(TypeToken.java:284)
at java.util.HashMap.getNode(HashMap.java:578)
at java.util.HashMap.get(HashMap.java:556)
at java.util.Collections$SynchronizedMap.get(Collections.java:2644)
at com.google.gson.Gson.getAdapter(Gson.java:332)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:55)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
...and so on

You are missing gsonBuilder.create(), so type adapters donsn't registered properly:
val gsonBuilder = new GsonBuilder
gsonBuilder.registerTypeAdapter(classOf[Author], new AuthorSerializer)
gsonBuilder.registerTypeAdapter(classOf[Book], new BookSerializer)
val book = Book("test book")
val author = Author("test author")
book.authors += author
val gson = gsonBuilder.create() // this line !!!
println(gson.toJson(author))
println(gson.toJson(book))

Related

I'm trying to get the document from the index in elasticsearch using Scala, but get the error

Code of Getting Document
Herr i have a case class User having some Attributes and have index "firstindex", i want to get the document on the bases of "id"
import co.elastic.clients.elasticsearch.core.{GetRequest, GetResponse}
import java.util.concurrent.CompletableFuture
class GetIndex {
def Getting(): Unit = {
val esClient = ElasticSearchConnection.getClient
val request: GetRequest = new GetRequest("firstindex", "1")
val response: CompletableFuture[GetResponse[User]] = esClient.get(request, classOf[User])
println(response)
}
}
Error
constructor GetRequest in class GetRequest cannot be accessed in class GetIndex from class GetIndex
val request: GetRequest = new GetRequest("firstindex", "1")

Scala JavaFx -- Cannot resolve overloaded method 'add' when trying to add tree table columns

I am trying to write an application using JavaFX and Scala (not ScalaFX). When I tried out this example from http://tutorials.jenkov.com/javafx/treetableview.html (Add TreeTableColumn to TreeTableView), I got a "Cannot resolve overloaded method 'add'" in the last two lines. I was wondering if you can help me get past this issue.
class Phase1 extends Application {
import javafx.scene.control.TreeTableColumn
import javafx.scene.control.TreeTableView
import javafx.scene.control.cell.TreeItemPropertyValueFactory
override def start(primaryStage: Stage): Unit = {
primaryStage.setTitle("Experimental Blocking Tree")
val scene = new Scene(new Group(), 1500, 800)
val sceneRoot = scene.getRoot.asInstanceOf[Group]
val treeTableView = new TreeTableView[Car]
val treeTableColumn1: TreeTableColumn[Car, String] = new TreeTableColumn[Car, String]("Brand")
val treeTableColumn2: TreeTableColumn[Car, String] = new TreeTableColumn[Car, String]("Model")
treeTableColumn1.setCellValueFactory(new TreeItemPropertyValueFactory[Car, String]("brand"))
treeTableColumn2.setCellValueFactory(new TreeItemPropertyValueFactory[Car, String]("model"))
treeTableView.getColumns.add(treeTableColumn1) // cannot resolve overloaded method here
treeTableView.getColumns.add(treeTableColumn2) // and here
}
}
Thanks in advance.
I had the same issue with displaying data in TreeTableView.
Jarek posted a solution here: GitHub Issue
Also this works for me:
import scalafx.beans.property.ReadOnlyStringProperty
case class Car (
val brand: ReadOnlyStringProperty,
val model: ReadOnlyStringProperty
)
class CarStringFactory(val stringValue: ReadOnlyStringProperty) extends scalafx.beans.value.ObservableValue[String, String] {
override def delegate: javafx.beans.value.ObservableValue[String] = stringValue
override def value: String = stringValue.get
}
class YourScalaFXApp {
// ... boilerplate code ...
import scalafx.scene.control.{TreeTableView, TreeTableColumn}
val treeTableView = new TreeTableView[Car]
val treeTableColumn1: TreeTableColumn[Car, String] = new TreeTableColumn[Car, String]("Brand"){
cellValueFactory = {p => new CarStringFactory(p.value.value.value.brand) }
}
val treeTableColumn2: TreeTableColumn[Car, String] = new TreeTableColumn[Car, String]("Model"){
cellValueFactory = {p => new CarStringFactory(p.value.value.value.model) }
}
treeTableView.getColumns.add(treeTableColumn1)
treeTableView.getColumns.add(treeTableColumn2)
}
Refer to
ScalaFX documentation: Properties
TreeTableColumn.cellValueFactory

the generation of parse tree of StanfordCoreNLP is stuck

When I use the StanfordCoreNLP to generate the parse using bigdata on Spark, one of the tasks had stuck for a long time. I looked for the error, it showed as follows:
at edu.stanford.nlp.ling.CoreLabel.(CoreLabel.java:68)
  at edu.stanford.nlp.ling.CoreLabel$CoreLabelFactory.newLabel(CoreLabel.java:248)
  at edu.stanford.nlp.trees.LabeledScoredTreeFactory.newLeaf(LabeledScoredTreeFactory.java:51)
  at edu.stanford.nlp.parser.lexparser.Debinarizer.transformTreeHelper(Debinarizer.java:27)
  at edu.stanford.nlp.parser.lexparser.Debinarizer.transformTreeHelper(Debinarizer.java:34)
  at edu.stanford.nlp.parser.lexparser.Debinarizer.transformTreeHelper(Debinarizer.java:34)
  at edu.stanford.nlp.parser.lexparser.Debinarizer.transformTreeHelper(Debinarizer.java:34)
  at edu.stanford.nlp.parser.lexparser.Debinarizer.transformTreeHelper(Debinarizer.java:34)
the relevant codes I think are as follows:
import edu.stanford.nlp.pipeline.Annotation
import edu.stanford.nlp.pipeline.StanfordCoreNLP
import java.util.Properties
import edu.stanford.nlp.ling.CoreAnnotations.SentencesAnnotation
import edu.stanford.nlp.trees.TreeCoreAnnotations.TreeAnnotation
import edu.stanford.nlp.util.CoreMap
import scala.collection.JavaConversions._
object CoreNLP {
def transform(Content: String): String = {
val v = new CoreNLP
v.runEnglishAnnotators(Content);
v.runChineseAnnotators(Content)
}
}
class CoreNLP {
def runEnglishAnnotators(inputContent: String): String = {
var document = new Annotation(inputContent)
val props = new Properties
props.setProperty("annotators", "tokenize, ssplit, parse")
val coreNLP = new StanfordCoreNLP(props)
coreNLP.annotate(document)
parserOutput(document)
}
def runChineseAnnotators(inputContent: String): String = {
var document = new Annotation(inputContent)
val props = new Properties
val corenlp = new StanfordCoreNLP("StanfordCoreNLP-chinese.properties")
corenlp.annotate(document)
parserOutput(document)
}
def parserOutput(document: Annotation): String = {
val sentences = document.get(classOf[SentencesAnnotation])
var result = ""
for (sentence: CoreMap <- sentences) {
val tree = sentence.get(classOf[TreeAnnotation])
//output the tree to file
result = result + "\n" + tree.toString
}
result
}
}
My classmate said the data used to test is recurse and thus the NLP is endlessly run. I don't know whether it's true.
If you add props.setProperty("parse.maxlen", "100"); to your code that will set the parser to not parse sentences longer than 100 tokens. That can help prevent crash issues. You should experiment with the best max sentence length for your application.

Scala: "recursive value ... needs type" but I use Java types only

object Rec extends App {
val outStream = new java.io.ByteArrayOutputStream
{
val out = new java.io.PrintStream(new java.io.BufferedOutputStream(outStream))
}
}
This seemingly simple code causes a compile error:
$ scalac rec.scala
rec.scala:2: error: recursive value out needs type
val outStream = new java.io.ByteArrayOutputStream
^
one error found
But I don't see what is "recursive."
Scala compiler version 2.11.7 -- Copyright 2002-2013, LAMP/EPFL
Background: I was trying to write a unit test on println with Console.withOut
After putting braces where they belong code looks like this:
object Rec extends App {
val outStream = new java.io.ByteArrayOutputStream {
val out = new java.io.PrintStream(new java.io.BufferedOutputStream(outStream))
}
}
and this is how you create object of an anonymous class with a member out that uses the defined object recursively (outStream uses outStream in its definition).
I believe this is what you wanted to do
object Rec extends App {
val outStream = new java.io.ByteArrayOutputStream
val out = new java.io.PrintStream(new java.io.BufferedOutputStream(outStream))
}
If you for some reason need to create another scope, you can use locally
What does Predef.locally do, and how is it different from Predef.identity
You are assigning a value to outStream by invoking stuff to which you pass on the outStream (I marked it in CAPS). Hence the recursion.
object Rec extends App {
val OUTSTREAM = new java.io.ByteArrayOutputStream
{
val out = new java.io.PrintStream(new java.io.BufferedOutputStream(OUTSTREAM))
}
}

Mockito class is mocked but returns nothing

I am kinda new with Scala and as said in the title, i am trying to mock a class.
DateServiceTest.scala
#RunWith(classOf[JUnitRunner])
class DateServiceTest extends FunSuite with MockitoSugar {
val conf = new SparkConf().setAppName("Simple Application").setMaster("local")
val sc = new SparkContext(conf)
implicit val sqlc = new SQLContext(sc)
val m = mock[ConfigManager]
when(m.getParameter("dates.traitement")).thenReturn("10")
test("mocking test") {
val instance = new DateService
val date = instance.loadDates
assert(date === new DateTime())
}
}
DateService.scala
class DateService extends Serializable with Logging {
private val configManager = new ConfigManager
private lazy val datesTraitement = configManager.getParameter("dates.traitement").toInt
def loadDates() {
val date = selectFromDatabase(datesTraitement)
}
}
Unfortunately when I run the test, datesTraitement returns null instead of 10, but m.getparameter("dates.traitement") does return 10.
Maybe i am doing some kind of anti pattern somewhere but I don't know where, please keep in mind that I am new with all of this and I didn't find any proper example specific to my case on internet.
Thanks for any help.
I think the issue is your mock is not injected, as you create ConfigManager inline in the DateService class.
Instead of
class DateService extends Serializable with Logging {
private val configManager = new ConfigManager
}
try
class DateService(private val configManager: ConfigManager) extends Serializable with Logging
and in your test case inject the mocked ConfigManager when you construct DateService
class DateServiceTest extends FunSuite with MockitoSugar {
val m = mock[ConfigManager]
val instance = new DateService(m)
}