getDeclaredMethod in Kotlin? - java

I have a question about "getDeclaredMethod" in kotlin.
I have a class:
class WorksheetFreeField : Serializable {
#SerializedName("val_value_1")
var val_value_1: String? = ""
#SerializedName("val_value_2")
var val_value_2: String? = ""
#SerializedName("val_value_3")
var val_value_3: String? = ""
Now I try this:
try {
val c = WorksheetFreeField::class
for (field in fields) {
val method = c.java.getDeclaredMethod("setVal_value_" + field.order)
Now I got this error in my catch:
com.werkbon.objects.WorksheetFreeField.setVal_value_1 []
What did I do wrong?

Take a look at c.java.declaredMethods in debug mode. Method setVal_value_1 exists, but has a parameter of type String.
So to make c.java.getDeclaredMethod work, you have to call it with 2 parameters: method name and String::class.java.

Related

How do you setup variables in build.gradle.kts

In build.gradle I Know you can do this
ext {
dbUsername = System.getenv("DB_USER").toString()
dbPassword = System.getenv("DB_PASS").toString()
libsUserNameNew = System.getenv("LIBS_USERNAME_NEW").toString()
libsPassNew = System.getenv("LIBS_PASS_NEW").toString()
gitShortTag = System.getenv("SHORT_SHA").toString()
repoName = System.getenv("REPO_NAME").toString()
group = "app.test.customerservicepoc"
mainClass = "app.test.customerservicepoc.CustomerServicePOC"
}
How can I achieve the same using build.gradle.kts
This is what I have tried
var dbUsername =""
var dbPassword =""
var LibsUserNameNew = ""
var LibsPassNew = ""
var gitShortTag = ""
var repoName = ""
and then
ext {
dbUsername = System.getenv("DB_USER").toString()
dbPassword = System.getenv("DB_PASS").toString()
kyoskLibsUserNameNew = System.getenv("LIBS_USERNAME_NEW").toString()
LibsPassNew = System.getenv("LIBS_PASS_NEW").toString()
gitShortTag = System.getenv("SHORT_SHA").toString()
repoName = System.getenv("REPO_NAME").toString()
group = "app.test.mms"
}
during build I end up getting errors
What went wrong: 945 Cannot invoke "String.toString()" because the return value of
"org.gradle.internal.classpath.Instrumented.getenv(String, String)" is
null
I am migrating the project to kotlin gradle, how can I define the variables in kotlin gradle?
Well, the issue is shown in the other question, System.getenv is a static java method that doesn't guarantee the nullability of the returned String. In Kotlin, this is a compilation error. So what the compiler is telling you is "I cannot guarantee that calling toString() on the returned string won't crash with a NullPointerException because the JVM method getenv doesn't guarantee it". I'd argue that you don't need the toString() call at all.
lateinit var db: String
// or
var db: String? = null //this can now be null
//then
ext {
db = System.getenv("YOUR_DB") ?: "" //UPDATE: you also need this since getenv can return null, or you need to make the variable `String?`
//or
db = System.getenv("YOUR_DB") ?: "" // since it can be null, set some fallback, like empty or null
}
This should work no problem.
UPDATE
I've created a new empty android project with compose (which uses build.gradle.kt instead of groovy), and added this:
lateinit var something1: String
var something2: String? = null
ext {
something1 = System.getenv("something") ?: ""
something2 = System.getenv("something2") ?: ""
}
It compiled no problem. (And I'd assume it would work if the environment variables were set).
BUILD SUCCESSFUL in 25s
Update 2 a real test
I've actually done this
lateinit var something1: String
var something2: String? = null
ext {
something1 = System.getenv("SHELL") ?: ""
something2 = System.getenv("SHELL") ?: ""
}
tasks.register("printSomething") {
println("Something 1 is $something1")
println("Something 2 is $something2")
}
Then I ran ./gradle printSomething
And here's the result:

MapStruct using default constructor over parameterised constructor of Kotlin data class(error: constructor in class cannot be applied to given types)

In my Micronaut Kotlin project I have two repositories. I am using MapStruct in both of them.
Source Class
#JsonInclude
data class Source(
var id: String,
var no: String,
var value: String,
)
Destination Class
#JsonInclude
data class Destination(
var id: String,
var no: String,
var value: String,
)
Mapper
#Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE)
interface SourceMapper {
fun convertToDestination(doc: Source): Destination
}
One of them first extracted the values of source class attributes and then passes these values to the parameterised constructor generated by kotlin data class
public Destination convertToDestination(Source doc){
if ( doc = = null ) {
return null;
}
String id = null;
String no = null;
String value = null;
id = doc.getId();
no = doc.getNo();
value= doc.getValue();
Destination d = new Destination(id, no,value);
}
Another one first creates the object then uses setter to assign value which fails at compile time as default constructor is not present for the data class.
public Destination convertToDestination(Source doc)
{
if ( doc == null ) {
return null;
}
Destination d = new Destination();
d.setId(doc.getId());
d.setNo(doc.getNo());
d.setValue(doc.getValue());
return d;
}
I have compared both the Gradle files and I am using same version of mapstruct.
```kapt("org.mapstruct:mapstruct-processor:1.5.0.RC1")``` and ```implementation("org.mapstruct:mapstruct:1.5.0.RC1")```
Please help me understand the behaviour and how we can control it.

An annotation argument must be a compile-time constant when trying to convert java enum

I tried to convert a java file to kotlin file but i'm getting this error : An annotation argument must be a compile-time constant
#StringDef(
BillingEnum.ALL,
BillingEnum.PAID,
BillingEnum.PENDING,
BillingEnum.OVERDUE,
BillingEnum.OPEN,
BillingEnum.DELETED
)
annotation class BillingEnum {
companion object {
var ALL = ""
var PAID = "paid"
var PENDING = "pending"
var OVERDUE = "overdue"
var OPEN = "open"
var DELETED = "deleted"
}
}
Before it looked like this:
#StringDef({
BillingEnum.ALL,
BillingEnum.PAID,
BillingEnum.PENDING,
BillingEnum.OVERDUE,
BillingEnum.OPEN,
BillingEnum.DELETED
})
public #interface BillingEnum {
String ALL = "";
String PAID = "paid";
String PENDING = "pending";
String OVERDUE = "overdue";
String OPEN = "open";
String DELETED = "deleted";
}
You must write
annotation class BillingEnum {
companion object {
const val ALL = ""
const val PAID = "paid"
const val PENDING = "pending"
const val OVERDUE = "overdue"
const val OPEN = "open"
const val DELETED = "deleted"
}
}

How to deserialize nested class with Gson in Kotlin?

I have json as in below, I'm really new on kotlin and i tried all examples but cannot set my nested class values when i convert to json
Here my json
{"Init":{"MOP":[{"Id":"1","Type":"0","ProtocolVersion":"1.0","MopCode":"*NEXB","TerminalId":"'P400Plus-275008565'","IP":"'192.168.1.15'","Currency":"EUR"},{"Id":"2","Type":"0","ProtocolVersion":"1.0","MopCode":"*NEXF","TerminalId":"'P400Plus-275008565'","IP":"'10.0.0.0:901'","Currency":"EUR"}]}}
Here my POJO
class Root {
#JsonProperty("Init")
var init: Init? = null
}
class MOP {
#JsonProperty("Id")
var id: String? = null
#JsonProperty("Type")
var type: String? = null
#JsonProperty("ProtocolVersion")
var protocolVersion: String? = null
#JsonProperty("MopCode")
var mopCode: String? = null
#JsonProperty("TerminalId")
var terminalId: String? = null
#JsonProperty("IP")
var ip: String? = null
#JsonProperty("Currency")
var currency: String? = null
}
class Init {
#JsonProperty("MOP")
var mop: List<MOP>? = null
}
Here my trial
val root: TestClass.Root = gson.fromJson(receiveString,TestClass.Root::class.java)
val initList = HashMap<String?,String?>()
if (root.init != null){
val mopList = root.init!!.mop
if (mopList != null) {
for (item in mopList){
initList.put(item.mopCode,item.id)
}
}
}
Always root.init and root.init.mop are null
What you can suggest me?
Thanks
Your Json construction has different tree.
You should use following structure:
data class Root (
#SerializedName("Init") val init : Init
)
data class Init (
#SerializedName("MOP") val mOP : List<MOP>
)
data class MOP (
#SerializedName("Id") val id : Int,
#SerializedName("Type") val type : Int,
#SerializedName("ProtocolVersion") val protocolVersion : Double,
#SerializedName("MopCode") val mopCode : String,
#SerializedName("TerminalId") val terminalId : String,
#SerializedName("IP") val iP : String,
#SerializedName("Currency") val currency : String
)
And you can parse just with:
Gson().fromJson(data,Root::class.java)
Also if you are using Gson, you should use SerializedName instead JsonProperty.

Gson does not map values in Java

I get this result from an API:
{"sessionID":"","randomKey":"","id":0,"userName":"","useIPAddress":"","usePortNo":"","response":{"code":-24,"message":"Incorrect credential","postedDateTime":null,"accountNo":0,"trxnNo":0,"changeTypeID":0}}
and my class is this:
class ResponseLoginParam {
val RandomKey: String? = null
val SessionID: String? = null
val UseIPAddress: String? = null
val UsePortNo: Int? = null
val UserName: String? = null
val Response: Response? = Response()
}
class Response {
val Code: Int? = null
val Message: String? = null
val PostedDateTime: String? = null
val AccountNo: Int? = null
val ChangeTypeID: Int? = null
}
for some reason it does not map to my object. But if I get the result like this:
{"SessionID":"","RandomKey":"","Id":0,"UserName":"","UseIPAddress":"","UsePortNo":"","Response":{"Code":-24,"Message":"Incorrect credential","PostedDateTime":null,"AccountNo":0,"TrxnNo":0,"ChangeTypeID":0}}
It is now capitalized, I can map the values properly. Why is this?
You need to either name class and json fields equally, or define serialization name:
class Response {
#SerializedName("code") // since its "code" in json
val Code: Int? = null
//no need for annotation because class field name equals json field name
val message: String? = null
}

Categories