I'm trying to save a serialize/deserialize a List of POJOS with Gson. While normally this isn't such a special task, I'm getting an exception that I've never seen before:
01-11 14:17:22.556: E/AndroidRuntime(15941): java.lang.RuntimeException:
Unable to start activity ComponentInfo{com.timkranen.playpalproject/com.timkranen.playpalproject.HomeActivity}:
java.lang.RuntimeException: Unable to invoke no-args constructor for interface java.util.concurrent.locks.Lock.
Register an InstanceCreator with Gson for this type may fix this problem.
I'm suspecting that it has something to with the fact that the List items are being loaded in an AsyncTask. Anyone have experience with this problem?
I've tried putting the logic that I execute within onSaveInstanceState (for saving) in a synchronized method, but that didn't help.
Edit
Here's some of my code to try and make it more clear. I've got a List that is called friendsList. The List is filled in this AsyncTask and is executed in onCreateView()
private class RetrieveFriends extends AsyncTask<Void, Integer, String> {
#Override
protected String doInBackground(Void... params) {
// get friends
if (friendProfiles == null || friendProfiles.size() == 0) {
friendProfiles = new ArrayList<Profile>();
if (currentProfile.getFriendUids() != null
&& currentProfile.getFriendUids().size() > 0)
for (String fUid : currentProfile.getFriendUids()) {
Profile friend = ProfileDataManager
.getProfileFromId(fUid);
friendProfiles.add(friend);
}
if (friendProfiles.size() == 0) {
return "null";
}
}
return "notnull";
}
#Override
protected void onPostExecute(String result) {
if (!result.equals("null")) {
loadingFriendsBar.setVisibility(View.INVISIBLE);
friendsList.setVisibility(View.VISIBLE);
FriendListAdapter adapter = new FriendListAdapter(
containedActivity, R.layout.friendslist_row,
friendProfiles);
friendsList.setAdapter(adapter);
} else {
loadingFriendsBar.setVisibility(View.INVISIBLE);
friendMsg.setVisibility(View.VISIBLE);
}
}
}
Now in the onSaveInstanceState I serialize that List to JSON like this:
private synchronized void saveToState(Bundle state) {
Gson gson = new Gson();
Type listOfProfiles = new TypeToken<List<Profile>>() {
}.getType();
String json = gson.toJson(friendProfiles, listOfProfiles);
state.putString("json_friendProfiles", json);
}
That method is called directly in onSaveInstanceState(). Retrieving it is the same:
private synchronized void retrieveFromState(String json) {
Type listOfProfiles = new TypeToken<List<Profile>>() {
}.getType();
Gson gson = new Gson();
friendProfiles = (List<Profile>) gson.fromJson(json,
listOfProfiles);
}
The weird thing is, the state is correctly saved when navigating to a different Fragment. The error only occurs when I change the orientation.
Edit: On request here's the Profile class
public class Profile {
private String mEmail;
private String mPassword;
private String uid;
// optional properties
private String name;
private String location;
private String about;
private ParseFile image; // not certain of data type
private List<String> friendUids;
public String getName() {
if (name == null || name.equals("")) {
return "Name unknown";
}
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLocation() {
if (location == null || location.equals("")) {
return "Location unknown";
}
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getAbout() {
if (about == null || about.equals("")) {
return "About unknown";
}
return about;
}
public void setAbout(String about) {
this.about = about;
}
public void setUid(String Uid) {
this.uid = Uid;
}
public String getUid() {
return this.uid;
}
public String getPassword() {
return mPassword;
}
public String getEmail() {
return mEmail;
}
public Profile(String email, String password) {
this.mEmail = email;
this.mPassword = password;
}
/*
* Saves a Profile and returns the profiles UID This is ONLY APPLICABLE for
* NEW profiles use the update method to update existing profile data
*/
public void saveToParse(SaveCallback saveCallBack) {
if (ProfileDataManager.IsRegistered(this) != true) {
ParseObject pObject = new ParseObject("Profiles");
pObject.put("email", this.mEmail);
pObject.put("password", this.mPassword);
pObject.saveInBackground(saveCallBack);
} else {
saveCallBack.done(new ParseException(ErrorCodes.ALREADY_REGISTERED,
"AlreadyRegistered"));
}
}
public void update() {
ParseQuery<ParseObject> query = ParseQuery.getQuery("Profiles");
query.getInBackground(this.uid, new GetCallback<ParseObject>() {
#Override
public void done(ParseObject object, ParseException e) {
if (e == null) {
// update the object
object.put("email", Profile.this.mEmail);
object.put("password", Profile.this.mPassword);
if (Profile.this.name != null) {
object.put("name", Profile.this.name);
}
if (Profile.this.location != null) {
object.put("location", Profile.this.location);
}
if (Profile.this.about != null) {
object.put("about", Profile.this.about);
}
if (Profile.this.image != null) {
object.put("profileImage", Profile.this.image);
}
if (Profile.this.friendUids != null
&& Profile.this.friendUids.size() != 0) {
object.put("friends", Profile.this.friendUids);
}
object.saveInBackground();
}
}
});
}
/*
* Use updateWithCallBack when you want to update an object but want to show
* the updated data immediatly using a callback, when calling this method
* make sure that currentProfile in HomeActivity is set to the new Profile!
*/
public void updateWithCallBack(final SaveCallback callBack) {
ParseQuery<ParseObject> query = ParseQuery.getQuery("Profiles");
query.getInBackground(this.uid, new GetCallback<ParseObject>() {
#Override
public void done(ParseObject object, ParseException e) {
if (e == null) {
// update the object
object.put("email", Profile.this.mEmail);
object.put("password", Profile.this.mPassword);
if (Profile.this.name != null) {
object.put("name", Profile.this.name);
}
if (Profile.this.location != null) {
object.put("location", Profile.this.location);
}
if (Profile.this.about != null) {
object.put("about", Profile.this.about);
}
if (Profile.this.image != null) {
object.put("profileImage", Profile.this.image);
}
if (Profile.this.friendUids != null
&& Profile.this.friendUids.size() != 0) {
object.put("friends", Profile.this.friendUids);
}
object.saveInBackground(callBack);
}
}
});
}
// retrieves the image, when done calls callback
public void retrieveProfileImage(GetDataCallback callBack) {
this.image.getDataInBackground(callBack);
}
public ParseFile getProfileImage() {
return this.image;
}
public void setProfileImage(ParseFile image) {
this.image = image;
}
public void saveProfileImage(Bitmap image) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 50, stream);
byte[] byteArray = stream.toByteArray();
String imgid = this.getUid() + "_profile_image.jpeg";
String fileNameForImage = this.getUid() + "_profile_image.jpeg";
this.image = new ParseFile(fileNameForImage, byteArray);
}
public List<String> getFriendUids() {
return this.friendUids;
}
public void addFriend(String uid) {
if (this.friendUids != null) {
friendUids.add(uid);
} else {
friendUids = new ArrayList<String>();
friendUids.add(uid);
}
}
public void setFriends(Object friends) {
ArrayList<String> f = (ArrayList<String>) friends;
this.friendUids = f;
}
}
Gson object
private Gson gson = new GsonBuilder().
setExclusionStrategies(new ParseExclusion()).
create();
Exclusion Class
private class ParseExclusion implements ExclusionStrategy {
public boolean shouldSkipClass(Class<?> arg0) {
return false;
}
public boolean shouldSkipField(FieldAttributes f) {
return (f.getDeclaredClass() == Lock.class);
}
}
Finally:
Type type = new TypeToken<List<Profile>>() {}.getType();
List<Profile>) friendProfiles = new ArrayList<Profile>();
friendProfiles = gson.fromJson(json,type);
Related
I'm gonna be honest I am panicking. I am doing an exam in a Java course and I have been stuck for some time now.
I have to implement a RSS Feader and I am currently doing methods to save and load subscribed feeds. I thought I got the saveSubscribedFeeds method right because it passes the JUnit Test but I am starting to think I have some kind of error in there so that the loadSubscribeFeeds method cannot work properly.
Here is the saveSubscribedFeeds method:
public void saveSubscribedFeeds(List<Feed> feeds, File feedsFile) {
FileWriter writer = null;
try {
writer = new FileWriter(feedsFile);
for(Feed f: feeds) {
writer.write(f + System.lineSeparator());
}
writer.close();
} catch (IOException e) {
e.getMessage();
}
}
For the loadSubscribedFeed method I already tried a Scanner, BufferedReader and FileInputStream and ObjectInputStream but nothing works. This is my current method:
public List<Feed> loadSubscribedFeeds(File feedsFile) {
Scanner s = null;
try {
s = new Scanner(feedsFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
List<String> listString = new ArrayList<>();
List<Feed> listFeed = new ArrayList<>();
while (s.hasNextLine()) {
listString.add(s.nextLine());
}
for(String f : listString) {
listFeed.add(new Feed(f));
}
return listFeed;
}
here is also the Feed class:
public class Feed implements Serializable, Comparable<Feed> {
private static final long serialVersionUID = 1L;
private String url;
private String title;
private String description;
private String publishedDateString;
private List<Entry> entries;
public Feed(String url) {
super();
this.url = url;
this.entries = new ArrayList<Entry>();
this.title = "";
this.description = "";
this.publishedDateString = "";
}
/**
* Creates an instance of a Feed and transfers the feed
* data form a SyndFeed object to the new instance.
* #param url The URL string of this feed
* #param sourceFeed The SyndFeed object holding the data for this feed instance
*/
public Feed(String url, SyndFeed sourceFeed) {
this(url);
setTitle(sourceFeed.getTitle());
setDescription(sourceFeed.getDescription());
if (sourceFeed.getPublishedDate() != null)
setPublishedDateString(FeaderUtils.DATE_FORMAT.format(sourceFeed.getPublishedDate()));
for (SyndEntry entryTemp : sourceFeed.getEntries()) {
Entry entry = new Entry(entryTemp.getTitle());
entry.setContent(entryTemp.getDescription().getValue());
entry.setLinkUrl(entryTemp.getLink());
entry.setParentFeedTitle(getTitle());
if (entryTemp.getPublishedDate() != null) {
entry.setPublishedDateString(FeaderUtils.DATE_FORMAT.format(entryTemp.getPublishedDate()));
}
addEntry(entry);
}
}
public String getUrl() {
return url;
}
public void setTitle(String title) {
this.title = title != null ? title : "";
}
public String getTitle() {
return title;
}
public void setDescription(String description) {
this.description = description != null ? description : "";
}
public String getDescription() {
return description;
}
public void setPublishedDateString(String publishedDateString) {
this.publishedDateString = publishedDateString != null ? publishedDateString : "";
}
public String getPublishedDateString() {
return publishedDateString;
}
/**
* Returns a short string containing a combination of meta data for this feed
* #return info string
*/
public String getShortFeedInfo() {
return getTitle() + " [" +
getEntriesCount() + " entries]: " +
getDescription() +
(getPublishedDateString() != null && getPublishedDateString().length() > 0
? " (updated " + getPublishedDateString() + ")"
: "");
}
public void addEntry(Entry entry) {
if (entry != null) entries.add(entry);
}
public List<Entry> getEntries() {
return entries;
}
public int getEntriesCount() {
return entries.size();
}
#Override
public boolean equals(Object obj) {
return (obj instanceof Feed)
&& ((Feed)obj).getUrl().equals(url);
}
#Override
public int hashCode() {
return url.hashCode();
}
#Override
public String toString() {
return getTitle();
}
#Override
public int compareTo(Feed o) {
return getPublishedDateString().compareTo(o.getPublishedDateString());
}
}
Maybe someone out there will be able to help me or guide me in the correct direction.
Thanks already in advance.
Hi I am just started with mvvm with repository pattern I am stuck with the API error
I am using the generic API Response class as per google official repo in java
/**
* Generic class for handling responses from Retrofit
*
* #param <T>
*/
public class ApiResponse<T> {
public ApiResponse<T> create(Throwable error) {
return new ApiErrorResponse<>(error.getMessage().equals("") ? error.getMessage() : "Unknown error\nCheck network connection");
}
public ApiResponse<T> create(Response<T> response) {
if (response.isSuccessful()) {
T body = response.body();
if (body instanceof GithubApiResponse) {
if (AppUtils.isValid((GithubApiResponse) body)) {
String errorMsg = "Empty Response.";
return new ApiErrorResponse<>(errorMsg);
}
}
if (body == null || response.code() == 204) { // 204 is empty response
return new ApiEmptyResponse<>();
} else {
return new ApiSuccessResponse<>(body);
}
} else {
String errorMsg = "";
try {
errorMsg = response.errorBody().string();
} catch (IOException e) {
e.printStackTrace();
errorMsg = response.message();
}
return new ApiErrorResponse<>(errorMsg);
}
}
/**
* Generic success response from api
*
* #param <T>
*/
public class ApiSuccessResponse<T> extends ApiResponse<T> {
private T body;
ApiSuccessResponse(T body) {
this.body = body;
}
public T getBody() {
return body;
}
}
/**
* Generic Error response from API
*
* #param <T>
*/
public class ApiErrorResponse<T> extends ApiResponse<T> {
private String errorMessage;
ApiErrorResponse(String errorMessage) {
this.errorMessage = errorMessage;
}
public String getErrorMessage() {
return errorMessage;
}
}
/**
* separate class for HTTP 204 resposes so that we can make ApiSuccessResponse's body non-null.
*/
public class ApiEmptyResponse<T> extends ApiResponse<T> {
}
}
and My networkBoundResource as like this
public abstract class NetworkBoundResource<ResultType, RequestType> {
private AppExecutors appExecutors;
private MediatorLiveData<Resource<ResultType>> results = new MediatorLiveData<>();
public NetworkBoundResource(AppExecutors appExecutors) {
this.appExecutors = appExecutors;
init();
}
private void init() {
// update LiveData for loading status
results.setValue((Resource<ResultType>) Resource.loading(null));
// observe LiveData source from local db
final LiveData<ResultType> dbSource = loadFromDb();
results.addSource(dbSource, new Observer<ResultType>() {
#Override
public void onChanged(#Nullable ResultType ResultType) {
results.removeSource(dbSource);
if (shouldFetch(ResultType)) {
// get data from the network
fetchFromNetwork(dbSource);
} else {
results.addSource(dbSource, new Observer<ResultType>() {
#Override
public void onChanged(#Nullable ResultType ResultType) {
setValue(Resource.success(ResultType));
}
});
}
}
});
}
/**
* 1) observe local db
* 2) if <condition/> query the network
* 3) stop observing the local db
* 4) insert new data into local db
* 5) begin observing local db again to see the refreshed data from network
*
* #param dbSource
*/
private void fetchFromNetwork(final LiveData<ResultType> dbSource) {
Timber.d("fetchFromNetwork: called.");
// update LiveData for loading status
results.addSource(dbSource, new Observer<ResultType>() {
#Override
public void onChanged(#Nullable ResultType ResultType) {
setValue(Resource.loading(ResultType));
}
});
final LiveData<ApiResponse<RequestType>> apiResponse = createCall();
results.addSource(apiResponse, new Observer<ApiResponse<RequestType>>() {
#Override
public void onChanged(#Nullable final ApiResponse<RequestType> requestObjectApiResponse) {
results.removeSource(dbSource);
results.removeSource(apiResponse);
/*
3 cases:
1) ApiSuccessResponse
2) ApiErrorResponse
3) ApiEmptyResponse
*/
if (requestObjectApiResponse instanceof ApiResponse.ApiSuccessResponse) {
Timber.d("onChanged: ApiSuccessResponse.");
appExecutors.diskIO().execute(new Runnable() {
#Override
public void run() {
// save the response to the local db
saveCallResult((RequestType) processResponse((ApiResponse.ApiSuccessResponse) requestObjectApiResponse));
appExecutors.mainThread().execute(new Runnable() {
#Override
public void run() {
results.addSource(loadFromDb(), new Observer<ResultType>() {
#Override
public void onChanged(#Nullable ResultType ResultType) {
setValue(Resource.success(ResultType));
}
});
}
});
}
});
} else if (requestObjectApiResponse instanceof ApiResponse.ApiEmptyResponse) {
Timber.d("onChanged: ApiEmptyResponse");
appExecutors.mainThread().execute(new Runnable() {
#Override
public void run() {
results.addSource(loadFromDb(), new Observer<ResultType>() {
#Override
public void onChanged(#Nullable ResultType ResultType) {
setValue(Resource.success(ResultType));
}
});
}
});
} else if (requestObjectApiResponse instanceof ApiResponse.ApiErrorResponse) {
Timber.d("onChanged: ApiErrorResponse.");
results.addSource(dbSource, new Observer<ResultType>() {
#Override
public void onChanged(#Nullable ResultType ResultType) {
setValue(
Resource.error(
((ApiResponse.ApiErrorResponse) requestObjectApiResponse).getErrorMessage(),
ResultType
)
);
}
});
}
}
});
}
private ResultType processResponse(ApiResponse.ApiSuccessResponse response) {
return (ResultType) response.getBody();
}
private void setValue(Resource<ResultType> newValue) {
if (results.getValue() != newValue) {
results.setValue(newValue);
}
}
// Called to save the result of the API response into the database.
#WorkerThread
protected abstract void saveCallResult(#NonNull RequestType item);
// Called with the data in the database to decide whether to fetch
// potentially updated data from the network.
#MainThread
protected abstract boolean shouldFetch(#Nullable ResultType data);
// Called to get the cached data from the database.
#NonNull
#MainThread
protected abstract LiveData<ResultType> loadFromDb();
// Called to create the API call.
#NonNull
#MainThread
protected abstract LiveData<ApiResponse<RequestType>> createCall();
// Returns a LiveData object that represents the resource that's implemented
// in the base class.
public final LiveData<Resource<ResultType>> getAsLiveData() {
return results;
}
}
my Repository looks like this
#Singleton
public class GithubRepository {
private GithubDao githubDao;
private GithubTrendingApiService githubApiService;
public GithubRepository(GithubDao githubDao, GithubTrendingApiService githubApiService) {
this.githubDao = githubDao;
this.githubApiService = githubApiService;
}
public LiveData<Resource<List<GithubEntity>>> getRepositories() {
return new NetworkBoundResource<List<GithubEntity>, GithubApiResponse>(AppExecutors.getInstance()) {
#Override
protected void saveCallResult(#NonNull GithubApiResponse item) {
List<GithubEntity> repositories = item.getItems();
githubDao.insertRepositories(repositories);
}
#Override
protected boolean shouldFetch(#Nullable List<GithubEntity> data) {
// Timber.d("shouldFetch: repo: " + data.toString());
// int currentTime = (int) (System.currentTimeMillis() / 1000);
// Timber.d("shouldFetch: current time: " + currentTime);
// int lastRefresh = data.getTimestamp();
// Timber.d("shouldFetch: last refresh: " + lastRefresh);
// Timber.d("shouldFetch: it's been " + ((currentTime - lastRefresh) / 60 / 60 / 24) +
// " days since this recipe was refreshed. 30 days must elapse before refreshing. ");
// if ((currentTime - data.getTimestamp()) >= Constants.RECIPE_REFRESH_TIME) {
// Timber.d("shouldFetch: SHOULD REFRESH RECIPE?! " + true);
// return true;
// }
// Timber.d("shouldFetch: SHOULD REFRESH RECIPE?! " + false);
return true;
}
#NonNull
#Override
protected LiveData<List<GithubEntity>> loadFromDb() {
return githubDao.getTrendingRepository();
}
#NonNull
#Override
protected LiveData<ApiResponse<GithubApiResponse>> createCall() {
return githubApiService.fetchTrendingRepositories();
}
}.getAsLiveData();
}
}
Can anyone tell me whats I am doing wrong because I am getting an API error? somehow I am not able to get the correct data that's why the database is also not filling up
my GithubAPi response class is this
public class GithubApiResponse {
public GithubApiResponse() {
this.items = new ArrayList<>();
}
public GithubApiResponse(List<GithubEntity> items) {
this.items = items;
}
private List<GithubEntity> items;
public List<GithubEntity> getItems() {
return items;
}
public void setItems(List<GithubEntity> items) {
this.items = items;
}
}
and the Entity class is this
#Entity
public class GithubEntity implements Parcelable {
public GithubEntity(#NonNull Long id, String author, String name, String avatar,
String url, String description, Integer stars, Integer forks, Integer currentPeriodStars, String language, String languageColor) {
this.id = id;
this.author = author;
this.name = name;
this.avatar = avatar;
this.url = url;
this.description = description;
this.stars = stars;
this.forks = forks;
this.currentPeriodStars = currentPeriodStars;
this.language = language;
this.languageColor = languageColor;
}
#NonNull
#PrimaryKey
private Long id;
#SerializedName("author")
#Expose
private String author;
#SerializedName("name")
#Expose
private String name;
#SerializedName("avatar")
#Expose
private String avatar;
#SerializedName("url")
#Expose
private String url;
#SerializedName("description")
#Expose
private String description;
#SerializedName("stars")
#Expose
private Integer stars;
#SerializedName("forks")
#Expose
private Integer forks;
#SerializedName("currentPeriodStars")
#Expose
private Integer currentPeriodStars;
#SerializedName("language")
#Expose
private String language;
#SerializedName("languageColor")
#Expose
private String languageColor;
#NonNull
public Long getId() {
return id;
}
public void setId(#NonNull Long id) {
this.id = id;
}
protected GithubEntity(Parcel in) {
author = in.readString();
name = in.readString();
avatar = in.readString();
url = in.readString();
description = in.readString();
if (in.readByte() == 0) {
stars = null;
} else {
stars = in.readInt();
}
if (in.readByte() == 0) {
forks = null;
} else {
forks = in.readInt();
}
if (in.readByte() == 0) {
currentPeriodStars = null;
} else {
currentPeriodStars = in.readInt();
}
language = in.readString();
languageColor = in.readString();
}
public static final Creator<GithubEntity> CREATOR = new Creator<GithubEntity>() {
#Override
public GithubEntity createFromParcel(Parcel in) {
return new GithubEntity(in);
}
#Override
public GithubEntity[] newArray(int size) {
return new GithubEntity[size];
}
};
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAvatar() {
return avatar;
}
public void setAvatar(String avatar) {
this.avatar = avatar;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getStars() {
return stars;
}
public void setStars(Integer stars) {
this.stars = stars;
}
public Integer getForks() {
return forks;
}
public void setForks(Integer forks) {
this.forks = forks;
}
public Integer getCurrentPeriodStars() {
return currentPeriodStars;
}
public void setCurrentPeriodStars(Integer currentPeriodStars) {
this.currentPeriodStars = currentPeriodStars;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getLanguageColor() {
return languageColor;
}
public void setLanguageColor(String languageColor) {
this.languageColor = languageColor;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(author);
dest.writeString(name);
dest.writeString(avatar);
dest.writeString(url);
dest.writeString(description);
if (stars == null) {
dest.writeByte((byte) 0);
} else {
dest.writeByte((byte) 1);
dest.writeInt(stars);
}
if (forks == null) {
dest.writeByte((byte) 0);
} else {
dest.writeByte((byte) 1);
dest.writeInt(forks);
}
if (currentPeriodStars == null) {
dest.writeByte((byte) 0);
} else {
dest.writeByte((byte) 1);
dest.writeInt(currentPeriodStars);
}
dest.writeString(language);
dest.writeString(languageColor);
}
}
can anyone guide me so that I can fix this issue? stuck here for 2 days
Hello folks this may be dumb question but as a beginner am struggling with this how to group values based on id in list, Now let me clarify you briefly am having set of objects like this :
ID:1,UserID:330
ID:2,UserID:303
ID:3,UserID:090
ID:1,UserID:302
ID:2,UserID:306
How my list should look like is(Json Format):
[{"ID":1,"UserID":[330,302]},{"ID":2,"UserID":[303,306]},{"ID":3,"UserID":[090]}]
Now let me post what i have tried so far:
final List<Integer>list=new ArrayList<>();
final List<SpareReturnModel>lisobj=new ArrayList<>();
int duplicate=0;
for(int i=0;i<tView.getSelected().size();i++){
Object o= tView.getSelected().get(i).getValue();
SpareReturnModel asset=(SpareReturnModel) o;
int flag=asset.getFlag();
if(flag==2) {
int warehouseid = asset.getWareHouseID();
asset.setWareHouseID(warehouseid);
int partid = asset.getSerialNoID();
list.add(partid);
}
else {
Log.d("s","no value for header");
}
if(duplicate!=asset.getWareHouseID()){
asset.setParlist(list);
asset.setWareHouseID(asset.getWareHouseID());
lisobj.add(asset);
list.clear();
}
duplicate=asset.getWareHouseID();
}
Gson gson=new Gson();
//this will convert list to json
String value=gson.toJson(listobj);
SpareReturn Model Class:
public class SpareReturnModel {
private Integer SerialNoID;
private String SerialNumber;
private List<Integer>parlist;
public List<Integer> getParlist() {
return parlist;
}
public void setParlist(List<Integer> parlist) {
this.parlist = parlist;
}
public Integer getFlag() {
return flag;
}
public void setFlag(Integer flag) {
this.flag = flag;
}
private Integer flag;
public Integer getWareHouseID() {
return WareHouseID;
}
public void setWareHouseID(Integer wareHouseID) {
WareHouseID = wareHouseID;
}
private Integer WareHouseID;
public Integer getSerialNoID() {
return SerialNoID;
}
public void setSerialNoID(Integer serialNoID) {
SerialNoID = serialNoID;
}
public String getSerialNumber() {
return SerialNumber;
}
public void setSerialNumber(String serialNumber) {
SerialNumber = serialNumber;
}
}
Can someone let me know how to achieve this am struggling with this.
I simplify your class to make solution clearer:
public class SpareReturnModel implements Comparable<SpareReturnModel> {
private Integer id;
private String userId;
public SpareReturnModel(Integer id, String userId) {
this.id = id;
this.userId = userId;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
#Override
public int compareTo(SpareReturnModel other) {
return this.getId().compareTo(other.getId());
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SpareReturnModel model = (SpareReturnModel) o;
if (id != null ? !id.equals(model.id) : model.id != null) return false;
return userId != null ? userId.equals(model.userId) : model.userId == null;
}
#Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (userId != null ? userId.hashCode() : 0);
return result;
}
}
and add JsonSpareReturnModel
public class JsonSpareRuturnModel implements Comparable<JsonSpareRuturnModel> {
private final List<SpareReturnModel> modelList;
private final Integer id;
public JsonSpareRuturnModel(List<SpareReturnModel> modelList) {
this.modelList = modelList;
this.id = modelList.get(0).getId();
}
private final String toJson() {
return String.format("{\"ID\":%s,\"UserID\":%s}", id, formatUserIdList());
}
private String formatUserIdList() {
StringBuilder builder = new StringBuilder("[");
Iterator<SpareReturnModel> modelIterator = modelList.iterator();
while (modelIterator.hasNext()) {
builder.append(modelIterator.next().getUserId());
if (modelIterator.hasNext()) {
builder.append(",");
}
}
builder.append("]");
return builder.toString();
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
JsonSpareRuturnModel that = (JsonSpareRuturnModel) o;
return id != null ? id.equals(that.id) : that.id == null;
}
#Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
}
#Override
public int compareTo(JsonSpareRuturnModel other) {
return this.id.compareTo(other.id);
}
#Override
public String toString() {
return toJson();
}
if you need to group by user id you need to sort your models according to id's
and place them to json format model:
public class Main {
public static void main(String[] args) {
List<SpareReturnModel> models = new ArrayList<>(Arrays.asList(
new SpareReturnModel(1, "330"),
new SpareReturnModel(2, "303"),
new SpareReturnModel(3, "090"),
new SpareReturnModel(1, "302"),
new SpareReturnModel(2, "306")
));
Map<Integer, List<SpareReturnModel>> groupById = new HashMap<>();
for (SpareReturnModel model : models) {
List<SpareReturnModel> listById = groupById.get(model.getId());
if (listById == null) {
groupById.put(model.getId(), new ArrayList<>(Arrays.asList(model)));
} else {
listById.add(model);
}
}
List<JsonSpareRuturnModel> jsonList = new ArrayList<>();
for (Map.Entry<Integer, List<SpareReturnModel>> pair : groupById.entrySet()) {
jsonList.add(new JsonSpareRuturnModel(pair.getValue()));
}
System.out.println(jsonList);
final String expected = "[{\"ID\":1,\"UserID\":[330,302]}, {\"ID\":2,\"UserID\":[303,306]}, {\"ID\":3,\"UserID\":[090]}]";
System.out.println(jsonList.toString().equals(expected));
}
}
I have a TableView and a form with some TextBox and ComboBox in my javafx application. I am trying to populate the form components with selected rows data from TableView. I can populate all the TextBox without any error or exception. But while setting values to ComboBoxes, it's throwing an ClassCastException, java.lang.ClassCastException: java.lang.String cannot be cast to entity.StockUOM.
This is my StringCoverter
unitCombo.setConverter(new StringConverter<StockUOM>() {
#Override
public String toString(StockUOM object) {
return object.getStockUOM();
}
#Override
public StockUOM fromString(String string) {
return null;
}
});
This is my entity.StockUOM class
#Entity
#Access(AccessType.PROPERTY)
#NamedQueries({
#NamedQuery(name = StockUOM.findStockUOM, query = "SELECT s from StockUOM s")
})
public class StockUOM implements Externalizable{
public final static String PREFIX = "entity.StockUOM.";
public final static String findStockUOM = PREFIX + "findStockUOM";
private IntegerProperty id;
private int _id;
private StringProperty stockUOM;
private String _stockUOM;
public StockUOM() {
if (id == null) {
id = new SimpleIntegerProperty(this, "id", _id);
}
if( stockUOM== null){
stockUOM= new SimpleStringProperty(this,"stockUOM",_stockUOM);
}
}
public StockUOM(String stockUOM) {
this();
this.stockUOM.set(stockUOM);
}
public IntegerProperty idProperty() {
if (id == null) {
id = new SimpleIntegerProperty(this, "id", _id);;
}
return id;
}
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
public final int getId() {
if (id == null) {
return _id;
} else {
return id.get();
}
}
public final void setId(int id) {
if (this.id == null) {
_id = id;
} else {
this.id.set(id);
}
}
public StringProperty stockUOMProperty() {
if( stockUOM== null){
stockUOM= new SimpleStringProperty(this,"stockUOM",_stockUOM);
}
return stockUOM;
}
public final String getStockUOM() {
if(stockUOM == null){
return _stockUOM;
}else{
return stockUOM.get();
}
}
public void setStockUOM(String stockUOM) {
if (this.stockUOM == null) {
_stockUOM=stockUOM ;
} else {
this.stockUOM.set(stockUOM);
}
}
#Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(getId());
out.writeChars(getStockUOM());
}
#Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
setId(in.readInt());
setStockUOM((String)in.readObject());
}
#Override
public String toString() {
return getStockUOM();
}
}
This is how i am setting values to ComboBox
unitCombo.setValue(newValue.getUnit());
Here newValue is the instance of StockUOM of ChangeListner which is listening on TableView row selection.
So what's wrong i am doing ? And what's the solution.
Thanks.
The problem is that most probably you defined your ComboBox like:
ComboBox unitCombo = new ComboBox();
So you missed to define the generic argument and you ended up with the raw type (your IDE most probably gives you a warning on this line).
At this point it is not specified what kind of objects do you want to display in the ComboBox.
When you do the following:
unitCombo.setValue(newValue.getUnit());
you set the valueProperty as a String value.
And then comes your converter:
unitCombo.setConverter(new StringConverter<StockUOM>() {
#Override
public String toString(StockUOM object) {
return object.getStockUOM();
}
#Override
public StockUOM fromString(String string) {
return null;
}
});
which expects StockUOM object being displayed, which does not happen hence the error.
You have to decide what kind of object do you want to display: if it is StockUOM, then declare the ComboBox as ComboBox<StockUOM> unitCombo = new ComboBox<StockUOM>();. After this you will have a compile time error on the line where you set the value for a String value, to fix that error you have to modify that line as unitCombo.setValue(newValue);. If you want to display String objects, the methodology is the same.
I am a beginner in android.I am calling a webservice from my android project which returns a json string as response which contain a xml formatted string as one entry.
String jsoncontent=restTemplate.getForObject(constr+"getAssetdata/{Id}", String.class, curAcct.getiD());
final GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Assets.class, new AssetDeserialiser());
final Gson gson = gsonBuilder.create();
Assets assetAcc = gson.fromJson(jsoncontent, Assets.class);
Toast.makeText(getApplicationContext(), assetAcc.getKeyValueData(), 68000).show();
Below is the json string that i got as webservice response
jsoncontent={"id":39,"name":"ICICI Bank","purchaseValue":6000.0,"purchaseDate":1402403751000,"keyValueData":"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><root><Description><Name>Tax and other payments</Name><Value>433</Value></Description><Description><Name>Add more details...</Name><Value></Value></Description></root>"}
But i am getting a null value for assetAcc.getKeyValueData() after deserialization,there is no isue with other fields in assets.How to solve this issue? Please help me.
AssetDeserialiser.java:
public class AssetDeserialiser implements JsonDeserializer<Assets> {
#Override
public Assets deserialize(JsonElement arg0, Type arg1, JsonDeserializationContext arg2) throws JsonParseException {
JsonObject jobject =arg0.getAsJsonObject();
final Assets asset = new Assets();
try{
asset.setId(jobject.get("id").getAsInt());
asset.setName(jobject.get("name").getAsString());
asset.setPurchaseValue(jobject.get("purchaseValue").getAsFloat());
asset.setPurchaseDate(new Timestamp(jobject.get("purchaseDate").getAsLong()));
asset.setKeyValueData(jobject.get("keyValueData").isJsonNull() ? "" : jobject.get("keyValueData").getAsString());
}catch(Exception es){
System.out.println("es "+es);
}
return asset;
}
}
Assets.java:
public class Assets implements Serializable{
private Integer id;
private String name;
private Float purchaseValue;
private Timestamp purchaseDate;
private String keyValueData;
public Assets() {
super();
// TODO Auto-generated constructor stub
}
public Assets(Integer id, String name, Float purchaseValue, Timestamp purchaseDate, String keyValueData) {
super();
this.id = id;
this.name = name;
this.purchaseValue = purchaseValue;
this.purchaseDate = purchaseDate;
this.keyValueData = keyValueData;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Float getPurchaseValue() {
return purchaseValue;
}
public void setPurchaseValue(Float purchaseValue) {
this.purchaseValue = purchaseValue;
}
public Timestamp getPurchaseDate() {
return purchaseDate;
}
public void setPurchaseDate(Timestamp purchaseDate) {
this.purchaseDate = purchaseDate;
}
public String getKeyValueData() {
return keyValueData;
}
public void setKeyValueData(String keyValueData) {
this.keyValueData = keyValueData;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result
+ ((keyValueData == null) ? 0 : keyValueData.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result
+ ((purchaseDate == null) ? 0 : purchaseDate.hashCode());
result = prime * result
+ ((purchaseValue == null) ? 0 : purchaseValue.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Assets other = (Assets) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (keyValueData == null) {
if (other.keyValueData != null)
return false;
} else if (!keyValueData.equals(other.keyValueData))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (purchaseDate == null) {
if (other.purchaseDate != null)
return false;
} else if (!purchaseDate.equals(other.purchaseDate))
return false;
if (purchaseValue == null) {
if (other.purchaseValue != null)
return false;
} else if (!purchaseValue.equals(other.purchaseValue))
return false;
return true;
}
#Override
public String toString() {
return name;
}
}
You can set this keyValueData after deserialisation from your json string that contain the xml string as below
String jsoncontent=restTemplate.getForObject(constr+"getAssetdata/{Id}", String.class, curAcct.getiD());
final GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Assets.class, new AssetDeserialiser());
final Gson gson = gsonBuilder.create();
Assets assetAcc = gson.fromJson(jsoncontent, Assets.class);
JSONObject jsonObj=new JSONObject(jsoncontent);
assetAcc.setKeyValueData(jsonObj.getString("keyValueData"));
1.Use Parcelable -its much faster.
2.Timestamp change to long. (Then can parce this value like this):
private String parceDate(data long){
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm");
try {
retrun df.format(your long from Assets.class);
}catch (Exception e){
return "";
}
}
UPDATE:
Y can change your getter and setter for use Timestamp object from Assets class like this:
public void setPurchaseDate(long purchaseDate){
this.purchaseDate=purchaseDate
}
public Timestamp getPurchaseDate(){
return new Timestamp(purchaseDate); //from java.sql.Timestamp;
}
You can use jackson for deserialization.
public class AssetDeserialiser extends JsonDeserializer<Asset> {
#Override
public Asset deserialize(JsonParser arg0, DeserializationContext arg1)
throws IOException, JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readTree(arg0);
final Asset asset = new Asset();
try{
asset.setId(mapper.readValue(node.get("id"),Integer.class));
asset.setName(mapper.readValue(node.get("name"),String.class));
asset.setPurchaseDate(mapper.readValue(node.get("purchaseDate"),Timestamp.class));
asset.setPurchaseValue(mapper.readValue(node.get("purchaseValue"),Float.class));
asset.setKeyValueData(mapper.readValue(node.get("keyValueData"), String.class));
}catch(Exception es){
System.out.println("es "+es);
}
return asset;
}
}
This may help you.
Also you will have to add "#JsonDeserialize(using=AssetDeserialiser.class)" at the beginning of your asset class. It is done like this:
#JsonDeserialize(using=AssetDeserialiser.class)
public class Asset implements Serializable{