Intellij IDEA returns different results with vs. without enabled REPL for Kotlin - kotlin

I create a Kotlin scratch file in Intellij IDEA and use my current project's module classpath in order to access all libraries of the project (i'm using Jackson in this example)
In both scenarios I have declared the following class:
class Test(var first: String = "a", var second: String = "b")
Without REPL enabled
val jsonAsString = "{\"first\": \"a\", \"second\":\"b\"}"
println(ObjectMapper().readValue(jsonAsString, Test::class.java).first) // prints out "a"
"a" is printed out as expected
With REPL enabled the ObjectMapper.readValue() throws the following exception
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `Line_2$Test` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (String)"{"first": "a", "second":"b"}"; line: 1, column: 2]
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1904)
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1349)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1415)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:351)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:184)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4674)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3629)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3597)

I reproduced the bug and created an issue - https://youtrack.jetbrains.com/issue/KTIJ-21598/Scratch-REPL:-%22InvalidDefinitionException:-Cannot-construct-inst. Feel free to follow it.

Related

OpenAPI Generator Kotlin Jackson

I use the openapi generator kotlin module to generate kotlin classes from my openapi.yaml file. The process works fine until I try to deserialize the received JSON in my code to a kotlin class using Jackson.
This is the generated class
data class Request (
#field:JsonProperty("name")
var name: kotlin.String,
)
This is the error I get
java.lang.IllegalArgumentException: Cannot construct instance of `...package.Request` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: UNKNOWN; byte offset: #UNKNOWN]
I noticed that when I remove the "#field:" part in the generated code, then everything works like a charm.
So now my question is can I either remove the #field from the generator or make Jackson deserialize it correctly?
The versions that I use are
jackson: 2.13.1
open-api-generator (gradle plugin): 5.3.0
I had the same error and registering the Kotlin Jackson module fixed it for me: https://github.com/FasterXML/jackson-module-kotlin

Gremlin Driver Cannot Deserialize Response from Germlin Servier Running Bitsy Database

I'm running a gremlin server with bitsy using the conf and properties file given in the github repo (https://github.com/lambdazen/bitsy/tree/master/src/test/resources/gremlin-server). I have, of course, changed dbPath to an appropriate path.
My client is a kotlin application running gremlin console. I have no problem executing queries that result in string or map values, for example:
val encodedPasswd = getg().V().has("user", "login", login).values<String>("password").next()
However, when attempting to get vertices from queries:
val user = getg().V().has("user", "login", login).next()
I get a deserialization error:
[gremlin-driver-loop-1] WARN org.apache.tinkerpop.gremlin.driver.ser.AbstractGraphSONMessageSerializerV2d0 - Response [PooledUnsafeDirectByteBuf(ridx: 7446, widx: 7446, cap: 7446)] could not be deserialized by org.apache.tinkerpop.gremlin.driver.ser.AbstractGraphSONMessageSerializerV2d0.
org.apache.tinkerpop.shaded.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `org.apache.tinkerpop.gremlin.driver.message.ResponseMessage` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (byte[])"{"requestId":"5e78c0ba-64d2-4b31-8b04-262c3fa2b3b8","status":{"message":"Error during serialization: Direct self-reference leading to cycle (through reference chain: com.lambdazen.bitsy.store.VertexBean[\"id\"])","code":599,"attributes":{"#type":"g:Map","#value":["stackTrace","org.apache.tinkerpop.gremlin.driver.ser.SerializationException: org.apache.tinkerpop.shaded.jackson.databind.exc.InvalidDefinitionException: Direct self-reference leading to cycle (through reference chain: com.lambdazen.bi"[truncated 6946 bytes]; line: 1, column: 2]
at org.apache.tinkerpop.shaded.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
at org.apache.tinkerpop.shaded.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1451)
at org.apache.tinkerpop.shaded.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1027)
at org.apache.tinkerpop.shaded.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1297)
at org.apache.tinkerpop.shaded.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:326)
at org.apache.tinkerpop.shaded.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
at org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONTypeDeserializer.deserialize(GraphSONTypeDeserializer.java:212)
at org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONTypeDeserializer.deserializeTypedFromObject(GraphSONTypeDeserializer.java:86)
at org.apache.tinkerpop.shaded.jackson.databind.deser.BeanDeserializerBase.deserializeWithType(BeanDeserializerBase.java:1178)
at org.apache.tinkerpop.shaded.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:68)
at org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
at org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3091)
at org.apache.tinkerpop.gremlin.driver.ser.AbstractGraphSONMessageSerializerV2d0.deserializeResponse(AbstractGraphSONMessageSerializerV2d0.java:134)
at org.apache.tinkerpop.gremlin.driver.handler.WebSocketGremlinResponseDecoder.decode(WebSocketGremlinResponseDecoder.java:50)
...
Cluster construction:
var cluster = Cluster.build()
.serializer (
GryoMessageSerializerV3d0 (
GryoMapper.build()
.addRegistry(BitsyIoRegistryV3d0.instance())
)
)
.serializer (
GraphSONMessageSerializerV3d0 (
GraphSONMapper.build()
.addRegistry(BitsyIoRegistryV3d0.instance())
.create()
)
)
.create()
and traversal source construction:
fun getg() : GraphTraversalSource {
return EmptyGraph.instance().traversal().withRemote(DriverRemoteConnection.using(cluster))
}
Relevant parts of my gradle:
dependencies {
...
implementation('org.apache.tinkerpop:gremlin-driver:3.3.4')
implementation("com.lambdazen.bitsy:bitsy:3.1.0")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.9.+")
}
Why can't the driver deserialise messages from the server? What do I change to allow it to?
I'm not completely sure, but I'm guessing that Bitsy lacks full support for GraphSON 3.0. If you look at its IoRegistry implementation it registers no custom serializers for GraphSON (just for Gryo):
https://github.com/lambdazen/bitsy/blob/c0dd4b6c9d6dc9987d0168c91417eb04d80bf712/src/main/java/com/lambdazen/bitsy/BitsyIoRegistryV3d0.java
I assume that's the reason why you get a serialization error. If you switch to just using Gryo (which is probably recommended to some extent since you are on the JVM with Kotlin) I imagine you won't have this problem.
Note that your Cluster object definition is not configuring the way you expect either. By calling serializer() twice (i.e. once for Gryo and once for GraphSON) you actually overwrite the Gryo configuration and simply configure the object to work with GraphSON.
So, I think you would just do this:
var cluster = Cluster.build()
.serializer (
GryoMessageSerializerV3d0 (
GryoMapper.build()
.addRegistry(BitsyIoRegistryV3d0.instance())
)
)
.create()

Kotlin Script Engine throws "unresolved reference", even if the package and class is valid

When using Kotlin's Script Engine, trying to import packages or use any class throws an "unresolved reference"
javax.script.ScriptException: error: unresolved reference: mrpowergamerbr
fun loritta(context: com.mrpowergamerbr.loritta.commands.CommandContext) {
^
This doesn't happen when running the class within IntelliJ IDEA, however it does happen when running the class on production.
While this YouTrack issue is related to fat JARs, this also can happen if you aren't using fat JARs (loading all the libraries via the startup classpath option or the Class-Path manifest option)
To fix this, or you can all your dependencies on your startup script like this:
-Dkotlin.script.classpath=jar1:jar2:jar3:jar4
Example:
java -Dkotlin.script.classpath=libs/dependency1.jar:libs/dependency2.jar:yourjar.jar -jar yourjar.jar
Or, if you prefer, set the property via code, using your Class-Path manifest option.
val path = this::class.java.protectionDomain.codeSource.location.path
val jar = JarFile(path)
val mf = jar.manifest
val mattr = mf.mainAttributes
// Yes, you SHOULD USE Attributes.Name.CLASS_PATH! Don't try using "Class-Path", it won't work!
val manifestClassPath = mattr[Attributes.Name.CLASS_PATH] as String
// The format within the Class-Path attribute is different than the one expected by the property, so let's fix it!
// By the way, don't forget to append your original JAR at the end of the string!
val propClassPath = manifestClassPath.replace(" ", ":") + ":Loritta-0.0.1-SNAPSHOT.jar"
// Now we set it to our own classpath
System.setProperty("kotlin.script.classpath", propClassPath)
While I didn't test this yet, in another unrelated answer it seems you can also supply your own classpath if you initialize the KotlinJsr223JvmLocalScriptEngine object yourself (as seen here)

How do you serialize a fragment of an Xtext parse tree/AST?

I have some xtend code that gets a parse tree/AST from a file in my DSL.
I want a method that will serialize any node in the tree. This means I want text in the language of my DSL for an EObject somewhere in the parse tree.
So, if a program in my language is
class C {
int foo = 3;
}
the parse tree might look like
MyProgram
|_ MyClass
|_MyFieldDecl
|_Type
| |_IntType
|_Identifier
|_Expression
|_LiteralInteger
If I assigned a variable x the MyFieldDecl object in the tree, then I might want to call
var s = serialize(x)
to get the String, "int foo = 3;"
So, how do I implement that serialize() function?
The code I find when searching around will serialize the entire tree but not a node/fragment.
I found things in the xtext core code that appear to be doing this with either some instance of ISerializer or GrammarAccessExtensions. I tried to inject
#Inject #Extension GrammarAccessExtensions _grammarAccessExtensions
and get the serialization using
val s = _grammarAccessExtensions.grammarFragmentToString(e, prefix);
where e is an EObject, some node in the parse tree.
That failed on the statement
val main = injector.getInstance(MyClass)
with this error:
Exception in thread "main" com.google.inject.ConfigurationException: Guice configuration errors:
1) No implementation for org.eclipse.xtext.xtext.generator.model.project.IXtextProjectConfig was bound.
while locating org.eclipse.xtext.xtext.generator.model.project.IXtextProjectConfig
for field at org.eclipse.xtext.xtext.generator.XtextGeneratorNaming.projectConfig(Unknown Source)
while locating org.eclipse.xtext.xtext.generator.XtextGeneratorNaming
for field at org.eclipse.xtext.xtext.generator.grammarAccess.GrammarAccessExtensions._xtextGeneratorNaming(Unknown Source)
while locating org.eclipse.xtext.xtext.generator.grammarAccess.GrammarAccessExtensions
for field at myorg.MyClass._grammarAccessExtensions(Unknown Source)
while locating myorg.MyClass
1 error
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1004)
at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:961)
at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1013)
at myorg.MyClass.main(MyClass.java:435)
I think this means I need to bind or inject things, but I just started working with this code base a couple of days ago, and all of this is new to me.
I also tried to copy code out of the xtext core to get an ISerializer and call
s = GrammarAccessExtensions.grammarFragmentToString(serializer, e, prefix)
That failed with this:
java.lang.NullPointerException: Invalid context: Grammar returns ScenarioModel

Using Forms after migrating from playframework 2.0 to 2.1 RC2 (java)

I have updated my controllers with to use play.data.Form.form() method instead of Controller.form(). When I try to run my application I get errors like:
error: method render in class create_user cannot be applied to given types;
return ok(create_user.render("", Form.form(CreateUserInfo.class), creator.get()));
required: String, play.api.data.Form, User
found: String, play.data.Form, User
It looks like the my templates expect to get play.api.data.Form instead of play.data.Form. Is there suppost to be any implicit conversion or should I update my templates to use play.data.Form?
If I'm using play.data.Form in my templates I am missing out on some of the features of play.api.data.Form, like the ability to request parameters through the apply method ( ex: createUserForm("username") )
The solution was provided by Guillaume Bort at the playframework google group.
I forgot to add javaCore as a dependency for my application after updating Build.scala. You have to explicitly add javaCore as a dependency in 2.1.
val appDependencies = Seq(
javaCore
)
And remember to start using play.Project instead of PlayProject:
val main = play.Project(appName, appVersion, appDependencies).settings(
// Add your own project settings here
)