Room Persistence: Entities and Pojos must have a usable public constructor - java

I am trying to add a database to my android app through the Room Persistence library and i am getting this error:
error: Entities and Pojos must have a usable public constructor. You can have an empty constructor or a constructor whose parameters match the fields (by name and type).
Tried the following constructors but they failed to match:
User(int,java.lang.String,java.lang.String,int,int,int,java.lang.String) -> [param:id -> matched field:unmatched, param:name -> matched field:unmatched, param:gender -> matched field:unmatched, param:age -> matched field:unmatched, param:weight -> matched field:unmatched, param:height -> matched field:unmatched, param:workout -> matched field:unmatched]
Here is my code:
#Entity
public class User {
#PrimaryKey
private int userId;
private String userName;
private String userGender;
private int userAge;
private int userWeight;
private int userHeight;
private String workoutPlan;
public User(int id, String name, String gender, int age, int weight, int height, String workout) {
this.userId = id;
this.userName = name;
this.userGender = gender;
this.userAge = age;
this.userWeight = weight;
this.userHeight = height;
this.workoutPlan = workout;
} ...
Can someone please tell me what i am doing wrong or what i missed?

Please change names of the parameters such that it matches entity attributes.
public User(int userId, String userName, String userGender, int userAge, int userWeight, int userHeight, String workoutPlan) {
this.userId = userId;
this.userName = userName;
this.userGender = userGender;
this.userAge = userAge;
this.userWeight = userWeight;
this.userHeight = userHeight;
this.workoutPlan = workoutPlan;
} ...
For persistance, it uses JavaBeans conventions in Room. For more information:
https://developer.android.com/training/data-storage/room/defining-data#java

Kotlin :
#Entity(tableName = "t_article_tabs")
data class WxArticleTabsEntity(
#ColumnInfo(name = "tabId") #PrimaryKey #SerializedName("id") val id: Int?,
#ColumnInfo(name = "tabName") #SerializedName("name") val name: String?,
...
#Ignore #SerializedName("children") val children: List<Any>?,
)
Change to :
#Entity(tableName = "t_article_tabs")
data class WxArticleTabsEntity(
#ColumnInfo(name = "tabId") #PrimaryKey #SerializedName("id") val id: Int?,
#ColumnInfo(name = "tabName") #SerializedName("name") val name: String?,
...
){
#Ignore #SerializedName("children") val children: List<Any>? = null
}

you can also try this:-
#Ignore
public User(int userId, String userName, String userGender, int userAge, int
userWeight, int userHeight, String workoutPlan ) {
this.userId = userId;
this.userName = userName;
this.userGender = userGender;
this.userAge = userAge;
this.userWeight = userWeight;
this.userHeight = userHeight;
this.workoutPlan = workoutPlan;
}
public User(String userName, String userGender, int userAge, int
userWeight, int userHeight, String workoutPlan) {
this.userName = userName;
this.userGender = userGender;
this.userAge = userAge;
this.userWeight = userWeight;
this.userHeight = userHeight;
this.workoutPlan = workoutPlan;
}

I got around this same problem by just adding a empty constructor.
public User(){}

I also got this error. Only one of my attributes in my constructor did not match and I was finding it rather confusing. My variable (outside the constructor) was named mURL and I was trying to match it to url within the constructor.
Instead, I should have set the outer variable to mUrl. Yes, capitalising the last 2 letters gave me that error. Setting this.mUrl = url instead of this.mURL = url solved the error.

In my case, I solved problem just removing #Ignore from default constructor.
If you copied your code from some place, and have #Ignore in default constructor then need to remove #Ignore from default constructor.
Before:
#Ignore
public Card(){}
After:
public Card(){}
I just added because it's happen with me.

Related

POJO serialization problems

In the past I have had no problems serializing and deserializing POJOs using GSon library. But ever since I modularization my project and updated my Android studio to 4.1, any POJO I try to serialize returns me a bad value here is an example.
The expected result
dSecBook.toString ==> DSecBook{sd='for the love of God and I not e', np='26.5', op='null', img='null', id='null'}
the result I'm getting
dSecBook.toJSon ==> {"b":"for the love of God and I not e","c":"26.5"}
Here is my POJO which is an SQL query derivative
public class DSecBook implements Serializable {
#ColumnInfo(name = "short_description")
public String sd;
#ColumnInfo(name = "newPrice")
public String np;
#ColumnInfo(name = "oldPrice")
public String op;
#ColumnInfo(name = "pro_download_thumbUrl")
public String img;
#ColumnInfo(name = "proID")
public String id;
public DSecBook() {
//for firebase
}
public DSecBook(String sd, String np, String op, String img, String id) {
this.sd = sd;
this.np = np;
this.op = op;
this.img = img;
this.id = id;
}
........
}
Problem is even firebase is giving the same result, this is killing my work
Please help

Add custom constructor to swagger generated model

I'm trying to add a custom constructor to a model generated by swagger, I was wondering if its possible for the model generation to be like below
example swagger model
#Schema(description = "Base Profile")
#javax.annotation.Generated(value = "io.swagger.codegen.v3.generators.java.JavaClientCodegen", date = "2020-10-08T18:15:35.865361-04:00[America/Vancouver]")
public class Account {
#SerializedName("id")
private Integer id = null;
#SerializedName("username")
private String username = null;
#SerializedName("lastModified")
private LocalDate lastModified = null;
#SerializedName("email")
private String email = null;
//getter setter
}
I need a constructor that does not contain the username and email
public Account(String username, String email)
Thanks

How work with immutable object in mongodb and lombook without #BsonDiscriminator

I tried to work with immutable objects in MongoDB and Lombok. I found a solution to my problem but it needs to write additional code from docs but I need to used Bson annotations and create a constructor where describes fields via annotations. But if I user #AllArgsConstructor catch exception: "Cannot find a public constructor for 'User'" because I can't use default constructor with final fields. I think i can customize CodecRegistry correctly and the example will work correctly but I couldn't find solution for it in docs and google and Stackoverflow.
Is there a way to solve this problem?
#Data
#Builder(builderClassName = "Builder")
#Value
#BsonDiscriminator
public class User {
private final ObjectId id;
private final String name;
private final String pass;
private final String login;
private final Role role;
#BsonCreator
public User(#BsonProperty("id") final ObjectId id,
#BsonProperty("name") final String name,
#BsonProperty("pass") final String pass,
#BsonProperty("login") final String login,
#BsonProperty("role") final Role role) {
this.id = id;
this.name = name;
this.pass = pass;
this.login = login;
this.role = role;
}
#AllArgsConstructor
public enum Role {
USER("USER"),
ADMIN("ADMIN"),
GUEST("GUEST");
#Getter
private String value;
}
public static class Builder {
}
}
Example for MongoDB where I create, save and then update users:
public class ExampleMongoDB {
public static void main(String[] args) {
final MongoClient mongoClient = MongoClients.create();
final MongoDatabase database = mongoClient.getDatabase("db");
database.drop();
final CodecRegistry pojoCodecRegistry = fromRegistries(MongoClientSettings.getDefaultCodecRegistry(),
fromProviders(PojoCodecProvider.builder().automatic(true).build()));
final MongoCollection<User> users = database.getCollection("users", User.class).withCodecRegistry(pojoCodecRegistry);
users.insertMany(new ExampleMongoDB().getRandomUsers());
System.out.println("Before updating:");
users.find(new Document("role", "ADMIN")).iterator().forEachRemaining(
System.out::println
);
System.out.println("After updating:");
users.updateMany(eq("role", "ADMIN"), set("role", "GUEST"));
users.find(new Document("role", "GUEST")).iterator().forEachRemaining(
System.out::println
);
}
public List<User> getRandomUsers() {
final ArrayList<User> users = new ArrayList<>();
for (int i = 0; i < 15; i++) {
users.add(
User.builder()
.login("log" + i)
.name("name" + i)
.pass("pass" + i)
.role(
(i % 2 == 0) ? User.Role.ADMIN : User.Role.USER
).build()
);
}
return users;
}
}
This should work (it worked for me):
#Builder(builderClassName = "Builder")
#Value
#AllArgsConstructor(onConstructor = #__(#BsonCreator))
#BsonDiscriminator
public class User {
#BsonId
private final ObjectId _id;
#BsonProperty("name")
private final String name;
#BsonProperty("pass")
private final String pass;
#BsonProperty("login")
private final String login;
#BsonProperty("role")
private final Role role;
}
Then in lombok.config add these (in your module/project directory):
lombok.addLombokGeneratedAnnotation=true
lombok.anyConstructor.addConstructorProperties=true
lombok.copyableAnnotations += org.bson.codecs.pojo.annotations.BsonProperty
lombok.copyableAnnotations += org.bson.codecs.pojo.annotations.BsonId
Also piece of advice, keep _id if you are going to use automatic conversion to POJOs using PojoCodec, which will save a lot of trouble.

Direct self-reference leading to cycle

I'm trying to send a request to get back an array of an object - Coupon when I submit the request I get the answer-
Direct self-reference leading to cycle (through reference chain:
java.util.HashSet[0] => model.Coupon["emptyCoupon"] => model.Coupon["emptyCoupon"])
The model.Coupon probably does the problem.
empty coupon is intended to be returned if the requested coupon does not exist.
public static final int NO_ID = -1;
private static final Coupon EMPTY_COUPON = new Coupon(NO_ID, null, null, null, NO_ID, NO_ID, null, NO_ID, null);
private long id = NO_ID;
private String title;
private LocalDate startDate;
private LocalDate endDate;
private int amount;
private int category;
private String message;
private double price;
private String image;
public Coupon() {
}
private Coupon(long id, String title, LocalDate start_date, LocalDate end_date, int amount, int category,
String message, double price, String image) {
this.id = id;
this.title = title;
this.startDate = start_date;
this.endDate = end_date;
this.amount = amount;
this.category = category;
this.message = message;
this.price = price;
this.image = image;
}
public Coupon getEmptyCoupon() {
return EMPTY_COUPON;
}
Before I added the EMPTY_COUPON I had no problems with the requests.
I want the emptyCoupon in the code, and I'll be happy to help
Since you are serializing to JSON or XML with Jersey, you may not have cycles in your object graph.
Jersey doesn't have a #JsonBackReference like Jackson does, so you might consider to move the EMPTY_COUPON in a separate class (something like Constants.java) and obtain it from there.
Other options are to add #XmlIgnore to your field or to switch to another JSON serializer like Jackson.

How to pass different constructors as response in java

Response.java
public class Response{
private String mobileNo;
private String contractId;
private String sim;
private String imei;
public Response(String mobileNo, String contractId){
this.mobileNo = mobileNo;
this.contractId = contractId;
}
public Response(String mobileNo, String contractId, String sim,
String imei, String identificationType) {
this.mobileNo = mobileNo;
this.contractId = contractId;
this.sim = sim;
this.imei = imei;
this.identificationType = identificationType;
}
//Getter and Setter
}
MainEx.java
public class MainEx{
Response response = null;
public Response response(){
String mobileNo = null;
String contractId = null;
String sim = null;
String imei = null;
if(something){
response= new IVRAccountDetailsRs("777","4545");
}
else{
response= new IVRAccountDetailsRs("777","4545","sim","imei");
}
return response;
}
}
When if statement call return response as
{ "mobileNo" = "777";
"contractId" = "4545";
"sim"= null;
"imei" = null;
}
But I want to get the response as bellow,
When calling if statement
Need to remove other two values.
{ "mobileNo" = "777";
"contractId" = "4545";
}
If contractId and mobileNo null then output should be
{ "mobileNo" = null;
"contractId" = null;
}
When calling else statement
{ "mobileNo" = "777";
"contractId" = "4545";
"sim"= "sim";
"imei" = "imei";
}
if all values null
{ "mobileNo" = null;
"contractId" = null;
"sim"= null;
"imei" =null;
}
Used Jackson version is 2.4.1
What can I do about this?
If the version of SpringBoot is less than 1.3, it can only be handled programmatically
#JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
public class Response {
///~
}
Spring boot can be configured directly from 1.3 in the application.properties file
spring.jackson.default-property-inclusion=non_null
Official documentation for the jacksong configuration
you can use #JsonInclude(JsonInclude.Include.NON_NULL) on sim and imei, Not on the whole class
public class Response{
private String mobileNo;
private String contractId;
#JsonInclude(JsonInclude.Include.NON_NULL)
private String sim;
#JsonInclude(JsonInclude.Include.NON_NULL)
private String imei;
public Response(String mobileNo, String contractId){
this.mobileNo = mobileNo;
this.contractId = contractId;
}
public Response(String mobileNo, String contractId, String sim,
String imei, String identificationType) {
this.mobileNo = mobileNo;
this.contractId = contractId;
this.sim = sim;
this.imei = imei;
this.identificationType = identificationType;
}
What you ask it's not possible to manage just with serialization.
I suggest to edit Response class, removing the field that don't want send when they are null.
Then create another class that extends Response, that have the other 2 fields.
At this point you can instantiate which one you want based on your condition and return anyway as a Response object.
public class SimpleResponse {
String mobileNo;
String contractId;
.....getters setters
}
public class FullResponse extends SimpleResponse {
String sim;
String imei;
....getter and setters
}
If you use jackson then add this:
#JsonInclude(JsonInclude.Include.NON_NULL) before field.
public class Response{
private String mobileNo;
private String contractId;
#JsonInclude(JsonInclude.Include.NON_NULL)
private String sim;
#JsonInclude(JsonInclude.Include.NON_NULL)
private String imei;
}
For jackson serializers:
You can use annotation over your class, to skip serializing null values:
#JsonInclude(Include.NON_NULL)
public class Response{...}
Or add a parameter to your ObjectMapper configuration:
mapper.setSerializationInclusion(Include.NON_NULL);
This may be a duplicate.
UPDATE:
You can also annotate properties.
#JsonInclude(JsonInclude.Include.NON_NULL)
private String sim;
#JsonInclude(JsonInclude.Include.NON_NULL)
private String imei;
This way other properties will serialize null values, but those two will not be serialized with null value.
Add this annotation just above the getter of sim and imei
#JsonInclude(Include.NON_NULL)
With Jackson > 1.9.11 and < 2.x use
#JsonSerialize
annotation to do that:
#JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
For the version above 2:
#JsonInclude(JsonInclude.Include.NON_NULL)

Categories