When will spring fix abstract mapping on couchbase reactive - spring-data-couchbase

Is there any solution how to use super type (abstract class) in spring boot starter data couchbase reactive ?
My idea is to have super type and save this super type into couchabse bucket, and read from it.
Writing is working perfectly, but on read I got exception:
org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.entities.Report]: Class is abstract
Classes are implemented like:
Report:
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "documentType"
)
#JsonSubTypes(
JsonSubTypes.Type(value = TestReport::class, name = TestReport.DOCUMENT_TYPE),
JsonSubTypes.Type(value = Test2Report::class, name = Test2Report.DOCUMENT_TYPE)
)
#Document
abstract class Report : SyncDocument {
var inspectorId: String = ""
var reportNumber: String = ""
var reportDate: Long = 0
constructor() : super(null) {}
}
TestReport:
#Document
#TypeAlias(TestReport.DOCUMENT_TYPE)
class TestReport : Report {
companion object {
const val DOCUMENT_TYPE: String = "TestReport"
}
var string3: String = ""
constructor() : super() {}
}
Test2Report:
#Document
#TypeAlias(Test2Report.DOCUMENT_TYPE)
class Test2Report : Report {
companion object {
const val DOCUMENT_TYPE: String = "Test2Report"
}
var string2: String = ""
constructor() : super() {}
}
I have implemented code in this way on other android project where ReactiveCrudRepository is not used, and works perfectly. Now I want to use same schema on ReactiveCrudRepository.
Thank you on any sugestions :D

It might help to see the complete stack trace and to know what version you are using.
In Java, you could simply make Report not Abstract. Does that not work in Android?
Thanks,
Mike

This is addressed in https://github.com/spring-projects/spring-data-couchbase/issues/1315 which is in 4.3.2 that was released today.

Related

Kotlin data class and bean validation with container element constraints

With Bean Validation 2.0 it is possible to also put constraints on container elements.
I cannot get this to work with Kotlin data classes:
data class Some(val someMap: Map<String, #Length(max = 255) String>)
This does not have any effect. Any ideas?
I created a repository with a sample project to reproduce the case: https://github.com/mduesterhoeft/bean-validation-container-constraints
Add this config to your build.gradle (note that ... means whatever is already there) :
Groovy:
compileKotlin {
kotlinOptions {
freeCompilerArgs = [..., "-Xemit-jvm-type-annotations"]
...
}
}
Kotlin DSL:
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf(..., "-Xemit-jvm-type-annotations")
...
}
}
Starting Kotlin 1.3.70 and 1.4, this should be possible setting a specific compiler option: https://kotlinlang.org/docs/reference/whatsnew14.html#type-annotations-in-the-jvm-bytecode .
On any previous version or any situation where this support is not sufficient, you have to write a custom validator.
Example one for validating that a collection only contains hex strings:
#Target(
AnnotationTarget.FUNCTION,
AnnotationTarget.PROPERTY_GETTER,
AnnotationTarget.PROPERTY_SETTER,
AnnotationTarget.FIELD,
AnnotationTarget.ANNOTATION_CLASS,
AnnotationTarget.CONSTRUCTOR,
AnnotationTarget.VALUE_PARAMETER
)
#Retention(AnnotationRetention.RUNTIME)
#MustBeDocumented
#Constraint(validatedBy = [HexStringElementsValidator::class])
annotation class HexStringElements(
val message: String = "must only contain hex values",
val groups: Array<KClass<*>> = [],
val payload: Array<KClass<out Any>> = []
)
class HexStringElementsValidator : ConstraintValidator<HexStringElements, Collection<Any>> {
companion object {
val pattern = "^[a-fA-F0-9]+\$".toRegex()
}
override fun isValid(value: Collection<Any>?, context: ConstraintValidatorContext?) =
value == null || value.all { it is String && pattern.matches(it) }
}

Supertype initialization is impossible without primary constructor

**How can I solved it**
// How can resolve This error from kotlin fragment *
open class First : Fragment() {
}
// 'Which is showing in image Fragment() was not access'
https://i.stack.imgur.com/Rcgl5.png
Fragments are special classes in Android and they need primary constructor (and that constructor is after name of class).
This constructor should by empty (if you declare any fields then you'll see warning, that you should not create Fragments with parameters).
So, all you need to compile your code is add brackets after fragment name:
class MyFragment() : Fragment() { /* some code here! remebmer about brackets after your MyFragment! */ }
Even more, you should avoid declaring any constructors with params.
You should create your fragments by Companion.newInstance(someArgs: List<Arg>) : YourFragment. (where Companion is companion object of your Fragment).
How fragments should be initialized you can find here: https://stackoverflow.com/a/9245510/7508302
Try adding constructor like this:
class First constructor() : Fragment() {
}
As you are using constructor below for passing fragmentManager there should be a default constructor when you are extending other class.
Try this code:
class MyFragment() : Fragment() {
constructor(supportFragmentManager:FragmentManager?) : this() {
}
}
Now you have 2 constructors:
No parameter ()
With an integer parameter (supportFragmentManager)
Here is full example, hope it could help.
Parent class:
open class ResponseModel {
var statusCode: Int = 0
var errorMessage: String = ""
constructor()
constructor(statusCode: Int) {
this.statusCode = statusCode
}
constructor(statusCode: Int, errorMessage: String) : this(statusCode) {
this.errorMessage = errorMessage
}
}
Child class:
class Response2Model : ResponseModel {
val a:String = ""
constructor(statusCode: Int, errorMessage: String) : super(statusCode, errorMessage)
constructor(a: String) : super() {
this.a = a
}
}

How to implement TornadoFX WebEngine Callback in Kotlin

I am using Kotlin TornadoFX to create a browser. When I implement WebEngine setCreatePopupHandler, I get an error:
e: surfing\src\surfing.kt: (76, 13): Modifier 'override' is not
applicable to 'local function'
e: surfing\src\surfing.kt: (76, 13): Expected a value of type WebEngine!
I referenced this Java code using JavaFX:
webEngine.setCreatePopupHandler(
new Callback<PopupFeatures, WebEngine>() {
#Override
public WebEngine call(PopupFeatures config) {
smallView.setFontScale(0.8);
if (!toolBar.getChildren().contains(smallView)) {
toolBar.getChildren().add(smallView);
}
return smallView.getEngine();
}
});
Translated into Kotlin to use TornadoFX:
var wv = webview()
val br = wv.getEngine()
br.setCreatePopupHandler(Callback<PopupFeatures, WebEngine>() {
override fun call(pf: PopupFeatures): WebEngine {
var smallView = webview()
val stage = Stage(StageStyle.UTILITY)
stage.setScene(Scene(smallView))
stage.show()
val engine = smallView.getEngine()
return engine
}
})
I have been searching for a long time on the internet, but I didn't find anything. Please can somebody help me fix this error.
You're almost there :) To create an anonymous class much the same way you do in Java, you need to use the object keyword in front of the class statement:
br.createPopupHandler = object : Callback<PopupFeatures, WebEngine> {
However, Kotlin allows you to turn SAM types into lambdas. You can also utilize the property access pattern and immutable values to clean up the code a little. Here is a the code rewritten and Kotlinified:
val wv = webview()
val br = wv.engine
br.setCreatePopupHandler {
val smallView = webview()
val stage = Stage(StageStyle.UTILITY)
stage.scene = Scene(smallView)
stage.show()
smallView.engine
}
I haven't really evaluated what you're doing here or if that's a good idea, so only take my advice on the syntax :)

TypeScript - passing a class as an argument, and reflection

I am writing a generic unmarshaller. It converts graph DB data to generated TypeScript (1.8.7) model classes. The input is JSON. The output should be an instance of a model class.
My ultimate goal is to create something like Hibernate OGM, only for Tinkerpop Frames and TypeScript, with REST endpoint in the middle.
What's the right way to pass a class as a parameter and reach it's static members? I want to have something like this:
SomeModel some = <SomeModel> unmarshaller.fromJSON({/*Object from JSON*/}, SomeModel);
I've tried to write a method.
Not sure if I am heading in the right direction, feel free to suggest different approaches.
public fromJSON(input: Object, clazz: typeof FrameModel): FrameModel
{
// This only demonstrates access to Framemodel's metadata
// about original Java model classes.
clazz.graphPropertyMapping;
clazz.graphRelationMapping;
let result = {};
...
return result;
}
...
But when I tried to execute this on Plunker, I got execution errors with unuseful stacktrace.
The model superclass looks like this:
/**
* Things common to all Frames models on the Typescript side.
*/
export class FrameModel
{
// Model metadata
static discriminator: string;
static graphPropertyMapping: { [key:string]:string; };
static graphRelationMapping: { [key:string]:string; };
// Each instance needs a vertex ID
private vertexId: number;
public getVertexId(): number {
return this.vertexId;
}
}
Sample model class:
import {TestPlanetModel} from './TestPlanetModel';
import {TestShipModel} from './TestShipModel';
export class TestGeneratorModel extends FrameModel
{
static discriminator: string = 'TestGenerator';
static graphPropertyMapping: { [key:string]:string; } = {
bar: 'boo',
name: 'name',
rank: 'rank',
};
static graphRelationMapping: { [key:string]:string; } = {
colonizes: 'colonizedPlanet',
commands: 'ship',
};
boo: string;
name: string;
rank: string;
public colonizedPlanet: TestPlanetModel[]; // edge label 'colonizedPlanet'
public ship: TestShipModel; // edge label 'ship'
}
I haven't found much material on reflection and class handling in TypeScript.
I know how I would do this in Java.
I know how I would do this in JavaScript.
I understand that I might achieve similar results with decorators, but having fields or static fields seemed a bit simpler, for generated models.
You've maybe already noticed that class members cannot have const keyword. But you could go with static instead. Also member should be public if you want it to be accessible from outside world.
public static graphPropertyMapping: { [key:string]:string; } = {
bar: 'boo',
name: 'name',
rank: 'rank',
};
As for creating result instance:
let result = new clazz();
//copy properties
return result;
If I understand you correctly then here's something to help you get started:
interface Model {}
interface ModelData {}
interface MyModelConstructor<M extends Model, D extends ModelData> {
new(data: D): M;
// static members
graphPropertyMapping: any;
graphRelationMapping: any;
}
class Unmarshaller {
public fromJSON<T>(input: string | ModelData, ctor: MyModelConstructor<T, ModelData>): T {
let data: ModelData = (typeof input === "string") ? JSON.parse(input) : input;
let propertyMapping = ctor.graphPropertyMapping;
let relationMapping = ctor.graphRelationMapping;
// do whatever with the mappings
return new ctor(input);
}
}
(code in playground)
I don't know how your models look like, so I hope this is close enough.
I recently released an enhanced version of the TypeScript compiler that allows exactly what you are expecting: read all (static or not) fields metadata from a class. For example you can write:
interface MyInterface {
active:boolean;
description: string;
}
class MyClass {
id: number;
name: string;
myComplexField: MyInterface;
}
function printMembers(clazz: Class) {
let fields = clazz.members.filter(m => m.type.kind !== 'function'); //exclude methods.
for(let field of fields) {
let typeName = field.type.kind;
if(typeName === 'class' || typeName === 'interface') {
typeName = (<Class | Interface>field.type).name;
}
console.log(`Field ${field.name} of ${clazz.name} has type: ${typeName}`);
}
}
printMembers(MyClass.getClass());
this is the output:
$ node main.js
Field id of MyClass has type: number
Field name of MyClass has type: string
Field myComplexField of MyClass has type: MyInterface
Of course, if you change the members property access of clazz to statics you will retrieve all static members. These information can be accessed at coding time too, so you can use autocompletion.
You can do the same with Interfaces metadata. Simply write MyInterface for example, and access its members.
You can find the project here.

Is it possible to define a generic type Vector in Actionsctipt 3?

Hi i need to make a VectorIterator, so i need to accept a Vector with any type. I am currently trying to define the type as * like so:
var collection:Vector.<*> = new Vector<*>()
But the compiler is complaining that the type "is not a compile time constant". i know a bug exists with the Vector class where the error reporting, reports the wrong type as missing, for example:
var collection:Vector.<Sprite> = new Vector.<Sprite>()
if Sprite was not imported, the compiler would complain that it cannot find the Vector class. I wonder if this is related?
So it looks like the answer is there is no way to implicitly cast a Vector of a type to valid super type. It must be performed explicitly with the global Vector.<> function.
So my actual problem was a mix of problems :)
It is correct to use Vector. as a generic reference to another Vector, but, it cannot be performed like this:
var spriteList:Vector.<Sprite> = new Vector.<Sprite>()
var genericList:Vector.<Object> = new Vector.<Object>()
genericList = spriteList // this will cause a type casting error
The assignment should be performed using the global Vector() function/cast like so:
var spriteList:Vector.<Sprite> = new Vector.<Sprite>()
var genericList:Vector.<Object> = new Vector.<Object>()
genericList = Vector.<Object>(spriteList)
It was a simple case of me not reading the documentation.
Below is some test code, I would expect the Vector. to cast implicitly to Vector.<*>.
public class VectorTest extends Sprite
{
public function VectorTest()
{
// works, due to <*> being strictly the same type as the collection in VectorContainer
var collection:Vector.<*> = new Vector.<String>()
// compiler complains about implicit conversion of <String> to <*>
var collection:Vector.<String> = new Vector.<String>()
collection.push("One")
collection.push("Two")
collection.push("Three")
for each (var eachNumber:String in collection)
{
trace("eachNumber: " + eachNumber)
}
var vectorContainer:VectorContainer = new VectorContainer(collection)
while(vectorContainer.hasNext())
{
trace(vectorContainer.next)
}
}
}
public class VectorContainer
{
private var _collection:Vector.<*>
private var _index:int = 0
public function VectorContainer(collection:Vector.<*>)
{
_collection = collection
}
public function hasNext():Boolean
{
return _index < _collection.length
}
public function get next():*
{
return _collection[_index++]
}
}
[Bindable]
public var selectedItems:Vector.<Category>;
public function selectionChange(items:Vector.<Object>):void
{
selectedItems = Vector.<Category>(items);
}
I believe you can refer to an untyped Vector by just calling it Vector (no .<>)
With Apache Flex 4.11.0, you can already do what you want. It might have been there since 4.9.0, but I have not tried that before.
var collection:Vector.<Object> = new Vector.<Object>()
maybe?
But i'm just speculating, haven't tried it.
var collection:Vector.<Object> = new Vector.<Object>()
but only on targeting flash player 10 cs4

Resources