AttachmentSortAttribute is not on the whitelist or annotated with #CordaSerializable - corda

When I query Attachments through RPC I get the following error:
net.corda.client.rpc.RPCException: Class "class net.corda.core.node.services.vault.AttachmentSort$AttachmentSortAttribute" is not on the whitelist or annotated with #CordaSerializable.
It only occurs if I include an AttachmentSort (vs leaving it null):
AttachmentSort attachmentSort = new AttachmentSort(
Collections.singletonList(
new AttachmentSort.AttachmentSortColumn(
AttachmentSort.AttachmentSortAttribute.INSERTION_DATE,
Sort.Direction.ASC
)
)
);
return cordaRPCOps.queryAttachments(
new AttachmentQueryCriteria.AttachmentsQueryCriteria(),
attachmentSort
);
In QueryCriteriaUtils.kt enum AttachmentSortAttribute is indeed not marked with a #CordaSerializable:
#CordaSerializable
data class AttachmentSort(val columns: Collection<AttachmentSortColumn>) : BaseSort() {
enum class AttachmentSortAttribute(val columnName: String) {
INSERTION_DATE("insertionDate"),
UPLOADER("uploader"),
FILENAME("filename"),
VERSION ("version")
}
#CordaSerializable
data class AttachmentSortColumn(
val sortAttribute: AttachmentSortAttribute,
val direction: Sort.Direction = Sort.Direction.ASC)
}
Am I maybe doing something wrong with my query or does AttachmentSortAttribute need to be changed?

Related

When will spring fix abstract mapping on couchbase reactive

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.

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 change a member field with Kotlin reflection?

I'm porting a class from Java to Kotlin. This class declares hundreds of objects. Each object has a name property which is identical with the declared variable name of the object. Java reflection allows to use the declared name via reflection to set the object member name. Just saves one parameter in hundreds of constructors.
I try to do the same in Kotlin but can't figure out how to do the property setting. Here is some simplified test code:
import kotlin.reflect.full.companionObject
import kotlin.reflect.full.declaredMemberProperties
class MyTestObject() {
var name: String = "NotInitialized"
companion object {
val Anton = MyTestObject()
val Berta = MyTestObject()
val Caesar = MyTestObject()
}
}
fun main(args : Array<String>) {
println(MyTestObject.Anton.name) // name not yet initialized
// Initialize 'name' with the variable name of the object:
for (member in MyTestObject::class.companionObject!!.declaredMemberProperties) {
if (member.returnType.toString() == "myPackage.MyTestObject") {
println("$member: ${member.name}")
// Set 'name' property to 'member.name':
// ???
}
}
println(MyTestObject.Anton.name) // now with the initialized name
}
The ??? line is where I would like to get access to the name property of MyTestObject to set it to to member.name. I'm looking for a function similar to (member.toObject() as MyTestObject).name = member.name.
While kotlin-reflection strives to be type-safe, sometimes the type system and the inference logic are not enough to allow for the things like what you are trying to do in a type-safe way. So, you have to make unchecked casts, stating that your knowledge about the types is more than the compiler can infer.
In your case, it's enough to cast member so that you can pass the companion object instance into its .get(...) and use the result as a MyTestObject, replace the // ??? line with:
#Suppress("UNCHECKED_CAST")
(member as KProperty1<Any, MyTestObject>)
.get(MyTestObject::class.companionObject!!.objectInstance!!)
.name = member.name
If you can replace MyTestObject::class.companionObject!! with MyTestObject.Companion::class (i.e. your actual use case does not involve getting .companionObject from different classes), the unchecked cast is not needed, and you can replace the statement above with this:
(member.get(MyTestObject.Companion) as MyTestObject).name = member.name
As an alternative that does not require companion object reflection at all, you can do the same binding logic with the delegation. Implementing provideDelegate allows you to customize the logic of initializing the property, and that's where you can assign the names:
operator fun MyTestObject.provideDelegate(
thisRef: MyTestObject.Companion,
property: KProperty<*>
) = apply { name = property.name }
operator fun MyTestObject.getValue(
thisRef: MyTestObject.Companion,
property: KProperty<*>
) = this
Then declare your properties as
val Anton by MyTestObject()
val Berta by MyTestObject()
val Caesar by MyTestObject()
Here is the final test code based on hotkey's solution:
package myPackage
import kotlin.reflect.full.declaredMemberProperties
class MyTestObject() {
lateinit var name: String
companion object {
val Anton = MyTestObject()
val Berta = MyTestObject()
val Caesar = MyTestObject()
init {
for (member in MyTestObject.Companion::class.declaredMemberProperties) {
if (member.returnType.toString() == "myPackage.MyTestObject") {
(member.get(MyTestObject.Companion) as MyTestObject).name = member.name
}
}
}
}
}
fun main(args : Array<String>) {
println(MyTestObject.Anton.name)
println(MyTestObject.Caesar.name)
}

Calling em.merge() on child entity gives parent object in return while using SINGLE_TABLE inheritence

Eclipselink 2.6.3 with JPA 2.0
I have an issue with SINGLE_TABLE inheritance strategy as you can see I have class A which is extended by Z & X. When I query and fetch List of Z or X entities and try to change something and update them one by one, in the process when I call em.merge() for fetching merged clone object it gives back class A which is strange.
As I already have class extractor which decides what class should be returned based on a specific field value.
This issue is intermittent and can't be replicated every time, I've also debugged in UnitOfWorkImpl method
public Object mergeCloneWithReferences(Object rmiClone, MergeManager manager) {
if (rmiClone == null) {
return null;
}
//this line should always give correct entity back.. but doesnt happen why ?
ClassDescriptor descriptor = getDescriptor(rmiClone);
if ((descriptor == null) || descriptor.isDescriptorTypeAggregate()) {
if (manager.getCascadePolicy() == MergeManager.CASCADE_BY_MAPPING){
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("not_an_entity", new Object[]{rmiClone}));
}
return rmiClone;
}
//CR#2272
logDebugMessage(rmiClone, "merge_clone_with_references");
ObjectBuilder builder = descriptor.getObjectBuilder();
Object implementation = builder.unwrapObject(rmiClone, this);
Object mergedObject = manager.mergeChanges(implementation, null, this);
if (isSmartMerge()) {
return builder.wrapObject(mergedObject, this);
} else {
return mergedObject;
}
}
Can someone point out what's going wrong ?
Class A
#Entity
#Table(name="TABLE_A")
#Customizer(ACustomizer.class)
#Inheritance(strategy=InheritanceType.SINGLE_TABLE)
#ClassExtractor(AExtractor.class)
#InstantiationCopyPolicy
#Cacheable
#Cache( alwaysRefresh=true,
refreshOnlyIfNewer=true,
expiry=300000,
coordinationType = CacheCoordinationType.SEND_NEW_OBJECTS_WITH_CHANGES)
public class A implements Serializable {
#Column(name="ABC")
private String abc;
//some fields
}
Class Z
#Entity
#Customizer(ZCustomizer.class)
public class Z extends A{
//some fields
}
class X
#Entity
public class X extends A{
//some fields
}

Resources