Rest webservice cannot deserialize date - android

I have an android application where user will input data about car. When they are done, they will press a button to sync their data. That is, on pressing the button it will call a rest webservice (Jersey) to synchronize the data with the server which will store the data in mysql.
I'm using hibernate/JPA/spring 4/jdk1.8 for the server side.
So basically both entity (android and server) should be same so that synchronization can take place. I'm having an issue when I'm synchronizing date. Both entity is using the same library java.util.date. Am getting this error :
Can not deserialize instance of java.util.Date out of START_OBJECT token
If both side is string , I don't have any issue. I also try to put the date field to type String on server, and on the android to type Date. It throws this exception:
Can not deserialize instance of java.lang.String out of START_OBJECT token
Any solution for this? I think the java.util on android and the one use in server side are not same.
Android Code: (am using google api client for json)
public class CarClient extends AbstractGoogleJsonClient {
public static final String DEFAULT_ROOT_URL = "";
public static final String DEFAULT_SERVICE_PATH = "..";
public static final String TOKEN_URL = DEFAULT_ROOT_URL + "....";
public static final String DEFAULT_BASE_URL = DEFAULT_ROOT_URL + DEFAULT_SERVICE_PATH;
public CarClient(com.google.api.client.http.HttpTransport transport,
com.google.api.client.json.JsonFactory jsonFactory,
com.google.api.client.http.HttpRequestInitializer httpRequestInitializer) {
this(new Builder(transport, jsonFactory, httpRequestInitializer));
}
public class MergeCar extends
CarRequest<Car> {
public MergeCar(Car cars) throws IOException {
super(CarClient.this,
HttpMethods.PUT,
DEFAULT_BASE_URL + "car_sync",
cars,
Car.class);
}
}
}
Android Car Entity:
#DatabaseTable(tableName = "CAR_TABLE")
public class Car implements Serializable {
private static final long serialVersionUID = 1L;
#Key("carId")
#DatabaseField(id = true, unique = true)
private String CAR_ID;
#Key("carName")
#DatabaseField
private String CAR_NAME;
#Key("createdDate")
#DatabaseField
private DATE CREATED_DATE;
//Getters and Setters .....
}

Related

Room: error: Not sure how to convert a Cursor to this method's return type (void)

I have this query set up to return all the records from these tables and display the information on a recyclerview in android. the DB is set up using the Room persistence library aka SQLITE.
#Query
("SELECT moodBeforetable.userId,
moodBeforetable.moodBefore,
moodBeforetable.cbtId,
cbtTable.automaticThought,
cbtTable.twistedThinkingPK,
cbtTable.challengeThought,
cbtTable.rationalThought,
cbtTable.date,
moodAfterTable.moodAfter,
twistedThinkingTable.twistedThinkingPK,
twistedThinkingTable.allOrNothing,
twistedThinkingTable.blamingOthers,
twistedThinkingTable.catastrophizing,
twistedThinkingTable.emotionalReasoning,
twistedThinkingTable.fortuneTelling,
twistedThinkingTable.labelling,
twistedThinkingTable.magnifyingTheNegative,
twistedThinkingTable.mindReading,
twistedThinkingTable.minimisingThePositive,
twistedThinkingTable.overGeneralisation,
twistedThinkingTable.selfBlaming,
twistedThinkingTable.shouldStatement
FROM moodBeforetable
JOIN cbtTable ON moodBeforetable.cbtId = cbtTable.cbtId
JOIN twistedThinkingTable ON cbtTable.cbtId = twistedThinkingTable.cbtId
JOIN moodAfterTable ON moodAfterTable.cbtId = cbtTable.cbtId
WHERE moodBeforetable.date >= datetime('now', '-1 year')
AND moodBeforetable.userId = :userId
ORDER BY :date DESC")
LiveData<List<MoodBeforeTable>> moodLogsAll (int userId, String date);
When I try to compile the app I get the following error:
The query returns some columns which are not used by com.example.feelingfit.persistence.tables.MoodBeforeTable.
You can use #ColumnInfo annotation on the fields to specify the mapping.
Could anyone help me debug this and find out why the app wont compile?
Problem is Room cannot map the result from your custom query to existing MoodBeforeTable. It is because your return type is List<MoodBeforeTable> but you have used joins using TwistedThinkingTable and MoodAfterTable and so on.
What you should do is create a new POJO like below:
public class MoodLogPojo() {
private int userId;
private String moodBefore;
zprivate int cbtId;
private String automaticThought;
private int twistedThinkingPK;
private String challengeThought;
private String rationalThought;
private String date;
private String moodAfter;
private int twistedThinkingPK;
private String allOrNothing;
private String blamingOthers;
private String catastrophizing;
private String emotionalReasoning;
private String fortuneTelling;
private String labelling;
private String magnifyingTheNegative;
private String mindReading;
private String minimisingThePositive;
private String overGeneralisation;
private String selfBlaming;
private String shouldStatement;
// generate getters and setters too
public void setSelfBlaming(Stirng selfBlming) {
this.selfBlming = selfBlming
}
public String getSelfBlaming() { return selfBlaming; }
// and so on ...
}
Then use this class as the return type like :
LiveData<List<MoodLogPojo>> moodLogsAll (int userId, String date);.
NOTE: Mind the MoodLogPojo class. Modify it accoring to the corresponding data types from each Entity.

Gson toJson not serializing specific values

I have this project I'm working on and I can't seem to get Gson to behave properly.
Here are the screenshots/files I will be referring to:
https://www.dropbox.com/sh/4qi2skij9knea7n/AACwkRV9x43lZeOoTZeCS3NPa?dl=0
I have my model, Trip:
public class Trip {
#Expose
#SerializedName("Id")
private String mId;
#Expose
#SerializedName("Name")
private String mName;
#Expose
#SerializedName("Date")
private String mShipmentDateString;
#Expose
#SerializedName("State")
private int mState;
#Expose
#SerializedName("Orders")
private List<Order> mOrders;
//Getters and setters
}
And that's it, nothing more.
I have created a separate project to try and understand this problem better, what I do in Main Activity is:
String jsonElement = JsonHelper.getString();
final TripResponse trips = new Gson().fromJson(jsonElement,
TripResponse.class);
TripRequest tripRequest = new TripRequest();
tripRequest.setTrips(trips.getTripList());
Gson gson = new GsonBuilder().serializeNulls().create();
String jsonWithBuilder = gson.toJson(tripRequest);
Gson gsonB2 = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().serializeNulls().create();
String object = gsonB2.toJson(tripRequest);
This is what I get, as you can see even though the dateString exists and has a value it doesn't get serialized:
(look at image1 in the folder).
The funny thing is: if I swap the SerializedName between dateString and name, suddenly it serializes the date and not the name: (as you can see in image2 on dropbox).
Input and output (output starts at line 118) are in the file "INPUTANDOUTPUT" in the dropbox folder.
What am I missing?
I think it's because your are using two differentes #annotation for the same purpose :
#Expose // serialize the variable as mId
private String mId
#SerializedName("Id") // serialize the variable as Id
private String mId;
You can try to use just #SerializedName
Hope this helps
Sorry for my english.

RealmObject is not valid, so it cannot be copied

Why is this code triggering a
java.lang.IllegalArgumentException: RealmObject is not valid, so it cannot be copied
error?
realm.beginTransaction();
realm.delete(Booking.class);
final Booking booking = realm.copyFromRealm(
new Booking(
editFragment.getDestination(),
editFragment.getDate()));
realm.commitTransaction();
However, if I change it to this the exception is not thrown:
realm.delete(Booking.class);
final Booking booking = realm.createObject(
Booking.class,
UUID.randomUUID().toString());
booking.setDestination(editFragment.getDestination());
booking.setDate(editFragment.getDate());
What is the difference?
The Booking class is defined as:
public class Booking extends RealmObject {
#Required
#PrimaryKey
private String id;
#Required
private String destination;
#Required
private Date date;
private int status;
private boolean isNotified;
public Booking() {
this.id = UUID.randomUUID().toString();
this.status = STATUS_UNAVAILABLE;
}
public Booking(String destination, Date date) {
this();
this.destination = destination;
this.date = date;
}
// Getters and setters follow
}
Edit:
Found what was wrong: I accidentally used copyFromRealm instead of copyToRealm. Looks like autocomplete sometimes works against you if you are not careful enough haha.
You have to pass a valid RealmObject into copyFromRealm(..) It is not sufficient to create a new instance on the fly, because the new object won't be attached to Realm.
Makes a standalone in-memory copy of an already persisted {#link RealmObject}.
In your second example you are creating a new object and passing it to the DB to be persisted: that are two very different operations.

Realm not saving (or possibly not returning) String values of related object

Realm not saving (or possibly not returning) String values of related object...
i have 3 models:
public class Customer extends RealmObject {
#Expose
#PrimaryKey
private Long id;
#Expose
private Long historicalId;
#Expose
private String versionUUID;
#Expose
private String nameCompany;
#Expose
private String email;
#Expose
private String phoneNumber;
#Expose
private String notes;
#Expose
private boolean active;
#Expose
private boolean currentVersion;
#Expose
private Date lastUpdated;
#Expose
private Date dateCreated;
public Customer() {
}
and
public class Project extends RealmObject {
#PrimaryKey
private Long id;
private Long historicalId;
private String versionUUID;
private String name;
private String description;
private String addressLineOne;
private String addressLineTwo;
private String addressCity;
private String addressState;
private String addressZip;
private String notes;
private Date lastUpdated;
private Date dateCreated;
private boolean active;
private boolean currentVersion;
private Customer customer;
private String customerVersion;
public Project() {
}
and lastly (added for the comment question)
public class Receipt extends RealmObject {
#PrimaryKey
private String id;
private String name;
private String vendor;
private Double amount;
private String description;
private Date dateCreated;
private Date lastUpdated;
private Date dateSynced;
private byte[] imageByteArray;
private Project project;
private String projectVersion;
private int imgWidht;
private int imgHeight;
public Receipt() {
}
i am saving the data via:
public static void syncAllDataToRealm(Context context){
Globals globals = Globals.getInstance();
Realm realm = Realm.getInstance(context);
realm.beginTransaction();
realm.copyToRealmOrUpdate(globals.getAllCustomers());
realm.copyToRealmOrUpdate(globals.getAllProjects());
realm.commitTransaction();
testRealCommit(context);
}
and i am verifying the data via
private static void testRealCommit(Context context){
Realm realm = Realm.getInstance(context);
RealmQuery<Customer> customerRealmQuery = realm.where(Customer.class);
RealmResults<Customer> customerRealmResults = customerRealmQuery.findAll();
logger.debug(LogUtility.generateMessage(TAG, "===== CUSTOMER ======= "));
for(Customer c: customerRealmResults){
logger.debug(LogUtility.generateMessage(TAG, c.getId() + " - " + c.getNameCompany()));
}
logger.debug(LogUtility.generateMessage(TAG, "===== CUSTOMER GLOBAL======= "));
for(Customer c: Globals.getInstance().getAllCustomers()){
logger.debug(LogUtility.generateMessage(TAG, c.getId() + " - " + c.getNameCompany()));
}
RealmQuery<Project> projectRealmQuery = realm.where(Project.class);
RealmResults<Project> projectRealmResults = projectRealmQuery.findAll();
logger.debug(LogUtility.generateMessage(TAG, "===== PROJECT ======="));
for(Project p: projectRealmResults){
logger.debug(LogUtility.generateMessage(TAG, p.getId() + " - " + p.getName()));
}
}
for some reason:
c.getNameCompany()
returns a null in the above code... if i dont add the project data to realm it works fine....
realm is bein set up in my Application file via:
RealmConfiguration config = new RealmConfiguration.Builder(context)
.name("receiptbucket.realm")
.schemaVersion(2)
.build();
Realm.setDefaultConfiguration(config);
any ideas???
found out something else... if i swap the commit order, adding all customers after adding all projects it works
realm.copyToRealmOrUpdate(globals.getAllProjects());
realm.copyToRealmOrUpdate(globals.getAllCustomers());
short term fix but i would like to know why i have to do it this way for the customer data to stick...
(New Issue)
now when i call copyOrUpdate for the Receipt it wipes all the customer data Projects Customer....
From your last description, I think the problem is the Project list returned by globals.getAllProjects() contains some Customer which has null value for nameCompany .
The reason is your Customer class has an id which is annotated with #PrimaryKey, when realm.copyToRealmOrUpdate(globals.getAllProjects()) called, Realm will create or update related objects recursively. (That is the whole point of update here).
If it finds a customer which has the same id and already saved in the Realm, it will just use all new values from Project.customer to update the one existed in the Realm. If the Procject.customer.nameCompany is null, you will have the problem you described above.
The solution would be make the globals.getAllProjects() return the latest value you want to update, since there is no way for Realm to understand whether the null values are something you want to ignore or update to.
i was able to overcome the last error by querying realm and reattaching the Customer that was getting nulled out to the Project which is part of the Receipt....
so then i started playing.... I was loading realm from Global data... I stopped that and loaded realm right when i got the data from my rest service...
upon doing that everything started just working correctly, lol...

Manually updating a foreign key.

I am pretty much aware of the absence of foreign keys in Realm. But I encountered this issue. I receive data in a normalised way and I have to figure out how to properly persist the relations.
Example:
class User{
private int id;
private Email email;
}
class Email{
private int id;
private String address;
}
And I receive something like:
{user={id:1, emailId:1}}
How can I store this type of data in my existing realm object ?
You will have to parse the JSON yourself to setup the links. From your description it isn't clear if you User and Email is already in Realm, but if that is the case I would do something like this:
class User{
#PrimaryKey
private int id;
private Email email;
}
class Email{
#PrimaryKey
private int id;
private String address;
}
JSONObject json = new JSONObject("{id:1, emailId:1}");
realm.beginTransaction();
User user = realm.where(User.class).equalTo("id", json.getInt("id")).findFirst();
Email email = realm.where(Email.class).equalTo("id", json.getInt("emailId")).findFirst();
user.setEmail(email);
realm.commitTransaction();

Categories

Resources