I am experimenting with aka and spray, what I want to achieve is a simple object marshalling service.
When I try to compile the code I get the following error :
Error:(33, 18) could not find implicit value for parameter marshaller:
spray.httpx.marshalling.Marshaller[ExampleApplication.Password]
marshal(Password(randomString(8),i,0))
^
Here is the code:
import akka.actor.ActorSystem
import spray.http.HttpEntity
import spray.json.DefaultJsonProtocol
import spray.routing.SimpleRoutingApp
import spray.httpx.marshalling._
import spray.json._
object ExampleApplication extends App with SimpleRoutingApp {
implicit val actorSystem = ActorSystem()
implicit var i = 0;
object MyJsonProtocol extends DefaultJsonProtocol {
implicit val PasswordFormat = jsonFormat3(Password)
}
case class Password(pass: String, count: Int, complexity: Int)
def newPass(cplx: Int):Password = {return Password(randomString(cplx),i,0)}
startServer(interface = "localhost", port = 8080) {
get {
path("passgen") {
i+=1
complete {
marshal(newPass(8))
}
}
}
}
def randomString(n: Int): String = {
n match {
case 1 => util.Random.nextPrintableChar().toString
case _ => util.Random.nextPrintableChar.toString ++ randomString(n - 1).toString
}
}
}
I'm still failing to understand what's going wrong.
Two changes to fix it:
import spray.httpx.SprayJsonSupport._
Then even though you define the JsonProtocol object right in your app you must still import it's members explicitly:
object MyJsonProtocol extends DefaultJsonProtocol {
implicit val PasswordFormat = jsonFormat3(Password)
}
import MyJsonProtocol._
That looks a little repetitive in this case, but in most use cases you'll have it defined somewhere else.
Optional
You can complete the call without explicitly calling marshal:
complete {
newPass(8)
}
Related
Consider the simplified Kotlin code below wherein a circular reference is resolved during JSONification via #JsonIdentityInfo, when using Jackson. A class Index contains a list indices of other Indexes
import com.fasterxml.jackson.annotation.JsonIdentityInfo
import com.fasterxml.jackson.annotation.ObjectIdGenerators
import com.fasterxml.jackson.databind.ObjectMapper
import java.util.UUID
fun main() {
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator::class, property = "id")
class Index() {
val id = UUID.randomUUID()
val neighbours = mutableListOf<Index>()
}
val n=1000 //does work for n=100
val indices = List(n) {Index()}
indices.forEach { it.neighbours.addAll(indices) }
ObjectMapper().writeValueAsString(indices)
}
The serialization fails for n=1000 but doesn't for n=100 hinting at a scaling issue.
I have gone through several SO answers as well as a very nice Baeldung blog (also found via SO) but those didn't help.
Why is there still a recursion error?
Interestingly the java version of the code works for both ns.
Is this a kotlin specific bug?
the gradle dependency being used
implementation "com.fasterxml.jackson.module:jackson-module-kotlin:2.13.+"
java version
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class rough {
public static void main(String[] args) throws JsonProcessingException {
#JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
class Index {
public UUID id = UUID.randomUUID();
List<Index> neighbours = new ArrayList<>();
}
var n = 1000;
List<Index> indices = new ArrayList<>(n);
for (int i = 0; i < n; i++) {
indices.add(new Index());
}
indices.forEach(index -> index.neighbours.addAll(indices));
new ObjectMapper().writeValueAsString(indices);
}
}
I'm working on creating desktop app using JavaFX, which allows you to scan qr codes from a webcam.
I decided to choose JavaCV to handle webcam capturning. However, the problem is that the CanvasFrame class creates a Swing JFrame. My main goal is to find the best way to integrate this with JavaFX components.
My question is whether it is possible to create CanvasFrame in JPanel(or other Swing/JavaFx component), not in JFrame. In this option I would wrap JPanel into SwingNode - it's solve my integration problem.
I'm also asking for other suggestions that solves JavaFX with JavaCV integration problem in my case.
Maybe there is a direct way to embed a camera screen into a JavaFx component.
I'm pasting the test code below. My code is written in kotlin, but it doesn't affect the problem:
import com.google.zxing.*
import com.google.zxing.client.j2se.BufferedImageLuminanceSource
import com.google.zxing.common.HybridBinarizer
import org.bytedeco.javacv.*
import java.awt.image.BufferedImage
import java.util.*
import java.util.concurrent.Executors
class Test {
companion object {
#JvmStatic
fun main(args: Array<String>) {
Executors.newSingleThreadExecutor().execute { testWebcam() }
}
private fun testWebcam() {
val grabber: OpenCVFrameGrabber = OpenCVFrameGrabber(0);
val canvasFrame: CanvasFrame = CanvasFrame("Cam")
grabber.start()
while (canvasFrame.isVisible) {
val frame: Frame = grabber.grabFrame() ?: break
canvasFrame.showImage(frame)
decodeQrCode(grabber)
}
}
private fun decodeQrCode(grabber: OpenCVFrameGrabber) {
val java2DFrameConverter: Java2DFrameConverter = Java2DFrameConverter()
val frame: Frame = grabber.grabFrame()
val image = java2DFrameConverter.getBufferedImage(frame)
val decodedQr = parseQr(image)
println(decodedQr)
}
private fun parseQr(image: BufferedImage): String? {
val reader: MultiFormatReader = MultiFormatReader()
val binaryBitmap: BinaryBitmap =
BinaryBitmap(HybridBinarizer(BufferedImageLuminanceSource(image)))
val hints: Hashtable<DecodeHintType, Any> = Hashtable()
hints[DecodeHintType.CHARACTER_SET] = "UTF-8"
hints[DecodeHintType.POSSIBLE_FORMATS] = listOf(BarcodeFormat.QR_CODE)
return try {
reader.decode(binaryBitmap, hints).text
} catch (e: NotFoundException) {
null;
}
}
}
}
There's a project at https://github.com/rladstaetter/javacv-webcam that has examples of using javacv with Swing, JavaFX, and a newer method of using a shared memory buffer between OpenCV and JavaFX's PixelBuffer.
Instead of using a CanvasFrame, you can use JavaFX's ImageView backed by a shared ByteBuffer. The pseudo-code is:
import java.nio.ByteBuffer
import javafx.scene.image._
import org.bytedeco.javacv.Frame
import org.bytedeco.opencv.global.opencv_imgproc._
import org.bytedeco.opencv.opencv_core.Mat
val videoView: ImageView = ImageView()
val grabber: OpenCVFrameGrabber = OpenCVFrameGrabber(0)
grabber.start()
// Fire off a thread to grab frames while the camera is active
// Each frame will ber passed to the updateView method below
// ... timer/thread omitted for brevity
val javaCVMat = Mat()
/** create buffer only once saves much time! */
val buffer: ByteBuffer = javaCVMat.createBuffer()
val formatByte: WritablePixelFormat<ByteBuffer> = PixelFormat.getByteBgraPreInstance()
fun updateView(frame: Frame): Unit = {
val w = frame.imageWidth()
val h = frame.imageHeight()
val mat = javaCVConv.convert(frame)
cvtColor(mat, javaCVMat, COLOR_BGR2BGRA)
val pb = PixelBuffer(w, h, buffer, formatByte)
val wi = WritableImage(pb)
videoView.setImage(wi)
}
I solved my problem. In my case, the best solution was to use Java2DFrameConverter:
import javafx.application.Application
import javafx.embed.swing.SwingFXUtils
import javafx.scene.Scene
import javafx.scene.image.ImageView
import javafx.scene.image.WritableImage
import javafx.scene.layout.VBox
import javafx.stage.Stage
import org.bytedeco.javacv.Frame
import org.bytedeco.javacv.Java2DFrameConverter
import org.bytedeco.javacv.OpenCVFrameGrabber
import java.awt.image.BufferedImage
import java.util.concurrent.Executors
class StackOverflow : Application() {
private val java2DFrameConverter: Java2DFrameConverter = Java2DFrameConverter()
companion object {
#JvmStatic
fun main(args: Array<String>) {
launch(StackOverflow::class.java)
}
}
override fun start(primaryStage: Stage) {
val grabber: OpenCVFrameGrabber = OpenCVFrameGrabber(0)
grabber.start()
val imageView: ImageView = ImageView()
Executors.newSingleThreadExecutor().execute {
while (true) {
val frame = grabber.grabFrame()
imageView.image = frameToImage(frame)
}
}
val scene: Scene = Scene(VBox(imageView), 800.0, 800.0)
primaryStage.scene = scene
primaryStage.show()
}
private fun frameToImage(frame: Frame): WritableImage {
val bufferedImage: BufferedImage = java2DFrameConverter.getBufferedImage(frame)
return SwingFXUtils.toFXImage(bufferedImage, null)
}
}
I've tried to get some json from this api: https://api.cointelegraph.com/api/v1/mobile/feed
I want to get the "title" field of each news. I created the class that supposed to get this fields and wrapper for this class, but I'm getting an empty list instead of this, i guess it's because I have to get field, which called "data" firstly and then parse it. So I changed my class for getting "title" fields to class for getting "data" field, but I'm still getting empty list.
I guess it's kinda stupid mistake, because it works with github api. I will put some kind of response below and my code. Thanks for trying to help.
Json response:
{"data":{"news":[{"type":"header","data":{"id":22358,"title":"MIT, Stanford Researchers to Fund New \u2018Globally Scalable\u2019 Cryptocurrency, \u2018Unit-e\u2019","lead":"Major U.S. universities including MIT, Stanford and UC Berkeley have teamed up to fund a new digital currency.","thumb":"https://s3.cointelegraph.com/storage/uploads/view/f7a7d42a1cba645f861ba810d2524f77.jpg","published_at":{"date":"2019-01-17 18:52:00.000000","timezone_type":3,"timezone":"Europe/London"},"share_url":"https://cointelegraph.com/news/mit-stanford-researchers-to-fund-new-globally-scalable-cryptocurrency-unit-e","views":2375,"type":"news","author":"Helen Partz","author_id":545,"tag":"Blockchain","badge":{"title":"News","label":"default"},"isSponsored":false,"audio":"https://s3.cointelegraph.com/audio/22358.71732d08-dc28-4787-98b1-46c4e0317916.mp3"}},{"type":"currencies","data":[{"price":3677.37,"name":"BTC","currency":"USD","isIncreased":1,"difference":"0.89"},{"price":123.57,"name":"ETH","currency":"USD","isIncreased":1,"difference":"0.17"},{"price":31.56,"name":"LTC","currency":"USD","isIncreased":1,"difference":"0.19"},{"price":0.33,"name":"XRP","currency":"USD","isIncreased":1,"difference":"1.22"}]}
Interface:
package com.hfad.cointask.service
import com.hfad.cointask.model.DataLIst
import com.hfad.cointask.model.NewsList
import retrofit2.Call
import retrofit2.http.*
interface CoinClient {
#GET("api/v1/mobile/feed")
fun getFeed(): Call<NewsList>
}
News class:
package com.hfad.cointask.model
class News (private var data: String) {
fun getData(): String{
return data
}
}
I've tried to get title in first time like that
package com.hfad.cointask.model
class News (private var title: String) {
fun getTitle(): String{
return title
}
}
My wrapper for News class:
package com.hfad.cointask.model
class NewsList {
var list = mutableListOf<News>()
}
My adapter:
package com.hfad.cointask.adapter
import android.support.v7.view.menu.MenuView
import android.support.v7.view.menu.MenuView.ItemView
import android.support.v7.widget.RecyclerView
import android.support.v7.widget.RecyclerView.ViewHolder
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import com.hfad.cointask.R
import com.hfad.cointask.model.News
class CoinAdapter(var values: List<News>): RecyclerView.Adapter<CoinAdapter.CoinViewHolder>() {
override fun onBindViewHolder(p0: CoinViewHolder, p1: Int) {
val itemTitle: News = values[p1]
p0.newsTitle.text = itemTitle.getData()
}
override fun getItemCount(): Int {
return values.size
}
override fun onCreateViewHolder(p0: ViewGroup, p1: Int): CoinViewHolder {
val view: View = LayoutInflater.from(p0.context).inflate(R.layout.news_item_view, p0, false)
return CoinViewHolder(view)
}
class CoinViewHolder(itemView: View): ViewHolder(itemView) {
var newsTitle: TextView = itemView.findViewById(R.id.item_title)
}
}
And my main activity:
package com.hfad.cointask
import android.os.Bundle
import android.support.design.widget.BottomNavigationView
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.widget.Toast
import com.hfad.cointask.adapter.CoinAdapter
import com.hfad.cointask.model.DataLIst
import com.hfad.cointask.model.News
import com.hfad.cointask.model.NewsList
import com.hfad.cointask.service.CoinClient
import kotlinx.android.synthetic.main.activity_feed.*
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class FeedActivity : AppCompatActivity() {
var news = mutableListOf<News>()
private lateinit var newsRecyclerView: RecyclerView
private lateinit var newsAdapter: CoinAdapter
private lateinit var layoutManager: LinearLayoutManager
private val client = mCoinClient().build()
private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.navigation_home -> {
message.setText(R.string.title_home)
return#OnNavigationItemSelectedListener true
}
R.id.navigation_dashboard -> {
message.setText(R.string.title_dashboard)
return#OnNavigationItemSelectedListener true
}
R.id.navigation_notifications -> {
message.setText(R.string.title_notifications)
return#OnNavigationItemSelectedListener true
}
}
false
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_feed)
newsRecyclerView = findViewById(R.id.news_recycler_view)
layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
newsRecyclerView.layoutManager = layoutManager
newsAdapter = CoinAdapter(news)
newsRecyclerView.adapter = newsAdapter
getNews().enqueue(object: Callback<NewsList>{
override fun onResponse(call: Call<NewsList>, response: Response<NewsList>) {
var jsonNews = response.body().list
news.clear()
news.addAll(response.body().list)
newsAdapter.notifyDataSetChanged()
}
override fun onFailure(call: Call<NewsList>?, t: Throwable?) {
val toast = Toast.makeText(this#FeedActivity, t.toString(), Toast.LENGTH_SHORT)
toast.show()
}
})
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
}
private fun getNews() = client.getFeed()
class mCoinClient {
private val builder = Retrofit
.Builder()
.baseUrl("https://api.cointelegraph.com/")
.addConverterFactory(GsonConverterFactory.create())
private val retrofit: Retrofit by lazy {
builder.build()
}
private val client: CoinClient by lazy {
retrofit.create(CoinClient::class.java)
}
fun build() = client
}
}
Thanks for any help
I think it you should change your Interface to
interface CoinClient {
#GET("api/v1/mobile/feed")
fun getFeed(): Call<Your Object that you want to receive it with>
}
The problem is in the map function while doing case class extraction. The case class is not serializable. I have defined formats DefaultFormats implicitly.
package org.apache.flink.quickstart
import java.util.Properties
import com.fasterxml.jackson.databind.{JsonNode, ObjectMapper}
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import org.apache.flink.api.scala._
import org.apache.flink.runtime.state.filesystem.FsStateBackend
import org.apache.flink.streaming.api.scala.{DataStream, StreamExecutionEnvironment}
import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer09
import org.apache.flink.streaming.util.serialization.SimpleStringSchema
import org.json4s.DefaultFormats
import org.json4s._
import org.json4s.native.JsonMethods
import scala.util.Try
case class CC(key:String)
object WordCount{
def main(args: Array[String]) {
implicit val formats = org.json4s.DefaultFormats
// kafka properties
val properties = new Properties()
properties.setProperty("bootstrap.servers", "***.**.*.***:9093")
properties.setProperty("zookeeper.connect", "***.**.*.***:2181")
properties.setProperty("group.id", "afs")
properties.setProperty("auto.offset.reset", "earliest")
val env = StreamExecutionEnvironment.getExecutionEnvironment
val st = env
.addSource(new FlinkKafkaConsumer09("new", new SimpleStringSchema() , properties))
.flatMap(raw => JsonMethods.parse(raw).toOption)
// .map(_.extract[CC])
val l = st.map(_.extract[CC])
st.print()
env.execute()
}
}
The error :
INFO [main] (TypeExtractor.java:1804) - No fields detected for class
org.json4s.JsonAST$JValue. Cannot be used as a PojoType. Will be
handled as GenericType
Exception in thread "main" org.apache.flink.api.common.InvalidProgramException: Task not
serializable
at org.apache.flink.api.scala.ClosureCleaner$.ensureSerializable(ClosureCleaner.scala:172)
at org.apache.flink.api.scala.ClosureCleaner$.clean(ClosureCleaner.scala:164)
at org.apache.flink.streaming.api.scala.StreamExecutionEnvironment.scalaClean(StreamExecutionEnvironment.scala:666)
at org.apache.flink.streaming.api.scala.DataStream.clean(DataStream.scala:994)
at org.apache.flink.streaming.api.scala.DataStream.map(DataStream.scala:519)
at org.apache.flink.quickstart.WordCount$.main(WordCount.scala:38)
at org.apache.flink.quickstart.WordCount.main(WordCount.scala)
Caused by: java.io.NotSerializableException: org.json4s.DefaultFormats$$anon$4
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at org.apache.flink.util.InstantiationUtil.serializeObject(InstantiationUtil.java:317)
at org.apache.flink.api.scala.ClosureCleaner$.ensureSerializable(ClosureCleaner.scala:170)
... 6 more
Process finished with exit code 1
The solution to to put
implicit val formats = org.json4s.DefaultFormats
outside the main function like
object WordCount{
implicit val formats = org.json4s.DefaultFormats
def main(args: Array[String])
OR lazily initialize formats like
implicit lazy val formats = org.json4s.DefaultFormats
inside the main function like
def main(args: Array[String]) {
implicit lazy val formats = org.json4s.DefaultFormats
I'm building a GUI with the SimpleSwingApplication trait in scala swing.
What I want to do is to provide a mechanism on close, that asks the user (Yes,No,Cancel) if he didn't save the document yet. If the user hits Cancel the Application shouldn't close. But everything I tried so far with MainFrame.close and closeOperation didn't work.
So how is this done in Scala Swing?
I'm on Scala 2.9.
Thanks in advance.
Slightly different variation from what Howard suggested
import scala.swing._
object GUI extends SimpleGUIApplication {
def top = new Frame {
title="Test"
import javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE
peer.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE)
override def closeOperation() { showCloseDialog() }
private def showCloseDialog() {
Dialog.showConfirmation(parent = null,
title = "Exit",
message = "Are you sure you want to quit?"
) match {
case Dialog.Result.Ok => exit(0)
case _ => ()
}
}
}
}
By using DO_NOTHING_ON_CLOSE you are given a chance to define what should be done when a WindowEvent.WINDOW_CLOSING event is received by the scala frame. When a scala frame receives a WINDOW_CLOSING event it reacts by calling closeOperation. Hence, to display a dialog when the user attempts to close the frame it is enough to override closeOperation and implement the desired behavior.
What about this:
import swing._
import Dialog._
object Test extends SimpleSwingApplication {
def top = new MainFrame {
contents = new Button("Hi")
override def closeOperation {
visible = true
if(showConfirmation(message = "exit?") == Result.Ok) super.closeOperation
}
}
}
I am not really familiar with scala swing but I found this code in some of my old test programs:
object GUI extends SimpleGUIApplication {
def top = new Frame {
title="Test"
peer.setDefaultCloseOperation(0)
reactions += {
case WindowClosing(_) => {
println("Closing it?")
val r = JOptionPane.showConfirmDialog(null, "Exit?")
if (r == 0) sys.exit(0)
}
}
}
}
This does what I wanted to do; calling super.closeOperation didn't close the frame. I would have just said that in a comment, but I am not yet allowed.
object FrameCloseStarter extends App {
val mainWindow = new MainWindow()
mainWindow.main(args)
}
class MainWindow extends SimpleSwingApplication {
def top = new MainFrame {
title = "MainFrame"
preferredSize = new Dimension(500, 500)
pack()
open()
def frame = new Frame {
title = "Frame"
preferredSize = new Dimension(500, 500)
location = new Point(500,500)
pack()
peer.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE)
override def closeOperation() = {
println("Closing")
if (Dialog.showConfirmation(message = "exit?") == Result.Ok) {
peer.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE)
close()
}
}
}
frame.open()
}
}