Kotlin Client Generator support for Enum Unknown Values - kotlin

I'm wondering if there is a way to generate a kotlin lib from an openapi spec that will support a default value if it doesn't serialize a known enum value.
Ex: the Java Generator has the enumUnknownDefaultCase flag in its spec
Ref from the kotlin generator seems to read in the config for the moshi serializer here
But unable to get this working by specifying the following two options via the kotlin generator:
"moshiCodeGen": "true"
"enumUnknownDefaultCase": "true"
Related conversation here
Thanks for any help figuring out how to get kotlin clients to not explode on new enumeration values.

If you are using openapi-generator-cli to generate code, the option enumUnknownDefaultCase should working by adding --additional-properties=enumUnknownDefaultCase=true
Example:
java -jar openapi-generator-cli-6.0.0.jar -i "example.com/swagger?format=openapi" -g kotlin --library=jwm-retrofit2 -o my-api-sdk --additional-properties=enumUnknownDefaultCase=true
It will create a SerializerHelper class which will add additional enum-adapter to Moshi builder like this
moshiBuilder
.add(MyEnum::class.java, EnumJsonAdapter.create(MyEnum::class.java).withUnknownFallback(MyEnum.unknown_default_open_api))
.add(...)
But it's not done yet, when initialize your ApiClient, you must force it to use MoshiBuilder with the enum-adapter, by default it won't use that one.
Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(ScalarsConverterFactory.create())
++ .addConverterFactory(MoshiConverterFactory.create(Serializer.moshi))
-- .addConverterFactory(MoshiConverterFactory.create(serializerBuilder.build()))
.apply {
if (converterFactory != null) {
addConverterFactory(converterFactory)
}
}

Related

How can I mock a call to Spring's repository `saveAll()` method using mockk?

I am using Mockk as my mocking framework when testing my Spring Boot Data repository interfaces.
Actually I am doing the following
every { itemRepository.saveAll(listOf(any(), any())) } returns listOf<Item>(mockk())
which should mock the following behaviour
val loot: List<Item> = itemGenerator.generateLoot(lootTable)
itemRepository.saveAll(loot)
The error message I receive is the following:
Failed matching mocking signature for
SignedCall(retValue=, isRetValueMock=true, retType=class kotlin.collections.Iterable, self=ItemRepository(#28), method=saveAll(Iterable), args=[[com.barbarus.gameserver.item.Item#ea00de, com.barbarus.gameserver.item.Item#23ca36d]], invocationStr=ItemRepository(#28).saveAll([com.barbarus.gameserver.item.Item#ea00de, com.barbarus.gameserver.item.Item#23ca36d]))
left matchers: [any(), any()]
The error message says left matchers: [any(), any()] pointing out that I somehow am not defining the expected arguments right.
I could fully define the items by real implementations in my test logic but I'd like to stick with mockk() just to keep the test code slim and fast.
However I kinda am not able to define the List<Item> with two elements using listOf(any(),any()) here. I tried other API of Mockk without any luck.
Any idea what to use in this case?
You should type the any() when you are passing into saveAll().
For instance:
import com.barbarus.gameserver.item.Item
...
every { itemRepository.saveAll(any<List<Item>>() } returns listOf<Item>(mockk())
Solution from another post

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

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)

Get pluginId stored in the IPreferenceNode in Eclipse

I am developing a plugin, in my plugin I want to get another plugin ID. I use the following code:
PreferenceManager pm = PlatformUI.getWorkbench( ).getPreferenceManager();
List<IPreferenceNode> list = pm.getElements(PreferenceManager.PRE_ORDER);
String pluginid;
// restoreDefValues("org.eclipse.ant.ui");
for(IPreferenceNode node : list){
the code to find the node related to the plugin;
}
When I debug the program, I can clearly see that in variable node(IPreferenceNode), it has the value of the pluginId. However, I check the document of IPreferenceNode, it seems that the neither IPreferenceNode nor the class PreferenceNode, provide a method to return the value of pluginId. I tried node.toString() as well, couldn't get the pluginId. So what should I do? Is there any other ways to get a plugin ID from another plugin?
Preference nodes created using the org.eclipse.ui.preferencePages extension point will actually be instances of org.eclipse.ui.internal.dialogs.WorkbenchPreferenceNode. The super class of this (WorkbenchPreferenceExtensionNode) contains the plugin id.
These classes are internal so you should not try to use them directly. However they implement org.eclipse.ui.IPluginContribution which can be used and has a getPluginId() method.
So something like:
if (node instanceof IPluginContribution) {
pluginId = ((IPluginContribution)node).getPluginId();
}
should work.

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
)