java.lang.IllegalArgumentException: invalid ObjectId [0] - java

I'm getting an java.lang.IllegalArgumentException: invalid ObjectId [0] when I try to do similar to the code below in one of my class.
String s = "0_abc";
--------
private ObjectId obj; [Instance variable]
public NewClass(String s){
String[] sarray = s.split("_");
obj = new ObjectId(sarray[0]);
}
What could be the possible reason for it to fail?

I assume ObjectId class is (org.bson.types.ObjectId) and it is used in the MongoDB Java driver.
What this exception means is that "0" cannot be pass as a value for the ObjectId construction.
Not every string is a correct ObjectId value. When ObjectId is initialized with the given string, validation is done. For example ObjectId requires string to have 24 characters. There are more constrains and you can find the complete validation source code in GitHub repo, in the method isValid().
If you want to create an ObjectId object with correct value you can create it using available factory method like this:
ObjectId obj = ObjectId.get()
This will create ObjectId with auto-generated value.

Unfortunately you have not sent the stacktrace but I think that the exception is thrown from constructor of your class ObjectId that does not allow sending 0 as an argument.

Related

Validating an object with properties all of type String checking that they will be able to be parsed to the correct data type

I have an entity that is populated directly from an Excel file so every property is of type String. I am then mapping from this property to an actual entity that has all of the correct data types set using parses with try catch. For example:
InputEntity:
public class ProductInput {
String name;
String color;
String price;
String date;
}
ActualEntity:
public class Product {
String name;
String color;
Double price;
Date date;
}
Prior to doing the actual mapping I would like to log any errors to the database using an Error class I created.
The ultimate goal would be to make sure each value coming from the InputEntity is not null or empty and is the correct type (able to be set in the Actual Entity without any error). I want to use reflection to loop through the fields of the Product class and find the matching field on the ProductInput class. Then checking its value with the correct parse function to make sure it will eventually be able to be set in the Product entity. If there is an error I am going to create an error record that includes the property name that failed and store it in the database saying which input field has a problem.
Is reflection the correct way to go about this? I want the function to be generic enough to handle any classes as the input and actual assuming the properties of the input entity will always be string and the property names will match.
I was thinking somewhere along the lines of:
public validateFields(Class<T> inputClass, Class<T> destinationClass) {
Field[] inputFields = inputClass.getDeclaredFields();
Field[] destinationFields = destinationClass.getDeclaredFields();
for (Field field: destinationFields) {
// Check for same field in inputClass
// If it exists confirm value of field is not null or empty
// Additionally confirm the value of field can be parsed to the type of the destinationField
// Create error entity with property name if there is a problem
}
}

Filter on an Integer field in Realm

If the id attribute in an object is of type Integer, how do I filter the query to return all objects whose id contains part of a query. i.e. what is the equivalent Realm contains filter operator for Integers?
e.g. object1 has id:1234. If I query 123 then it should return object1. The only filter available for Integers that comes close is equalTo but for this to work I would have to pass 1234 to the query.
Probably you need to add helper field that represent your id as String and query contains() based on this field.
You need to change your Integer field to String and then you can filter from Realm in this way
realm.where(YourRealmModel.class).contains("id","123").findAll()
It appears you're trying to access an object via it's a primary key of id. You can access that object directly with the following code without a query. Assuming we have a DogClass:
class DogClass: Object {
#objc dynamic var id = NSUUID().uuidString
#objc dynamic var dog_name = ""
override static func primaryKey() -> String? {
return "id"
}
}
let realm = try! Realm()
let primaryKey = 123
guard let thisDog = realm.object(ofType: DogClass.self, forPrimaryKey: primaryKey) else { return }
print(thisDog.dog_name)

How to handle optional keys in JSON response with Java

"app":{
"icon":{
"icon":"TOP_RATED"
},
"message":{
"_type":"TextSpan",
"text":"Top Rated"
}
}
I keep seeing the following code in one of the projects that I have inherited. The JSON response above is parsed as follows
// itemObject has the entire json response
// appObject is a POJO with icon, type fields
String icon= JsonPath.with(itemObject).getAsString("icon/icon");
appObject.setIcon(icon);
String type = "";
try {
type = JsonPath.with(itemObject).getAsString("message/_type");
catch(IllegalArgumentException e) {
// do nothing if type is not found in response
} finally {
// set type to empty string if it's not found
appObject.setType(type);
}
In the scenario, when _type doesn't exist for a specific app, would it be best to surround it with a try/catch block as shown above? It just seems wrong to use try/catch/finally block to process business logic instead of error handling. What is a better way to do the same and can Java 8 Optional help with this?
I find the org.json package simple and straightforward. It is found here. The org.json.JSONObject class, for example, contains the public boolean has(String key) method, which is used to check if a certain key exists.
Returns true if this object has a mapping for name. The mapping may be NULL.
You can check this way where 'HAS' - Returns true if this object has a mapping for name. The mapping may be NULL.
if (json.has("status")) {
String status = json.getString("status"));
}
if (json.has("club")) {
String club = json.getString("club"));
}
You can also check using 'isNull' - Returns true if this object has no
mapping for name or if it has a mapping whose value is NULL.
if (!json.isNull("club"))
String club = json.getString("club"));
http://developer.android.com/reference/org/json/JSONObject.html#has(java.lang.String)

Design for large scale parameter validation for JPA?

I have a method that takes in a JSON and takes out the data and distributes it to various strings so that they can be set in an entity and persisted. My example below is quite simple but for my actual code I have about 20+ fields
For example see
public Projects createProject(JsonObject jsonInst) {
Projects projectInst = new Projects();
String pId = jsonInst.get("proId").getAsString();
String pName = jsonInst.get("proName").getAsString();
String pStatus = jsonInst.get("proStatus").getAsString();
String pCustId = jsonInst.get("proCustId").getAsString();
String pStartDate = jsonInst.get("proStartDate").getAsString();
...
//Set the entity data
projectInst.setProjectId(pId);
projectInst.setProjectName(pName);
...
Notice if a varible dosent have a corrosponding entry in the Json this code will break with null pointer exception. Obviously I need to validate each parameter befopre calling .getAsString()
What is the best way to do this from a readability point of view I could create 2 varibles for each parameter and check and set for example.
if(jsonInst.get("proName")){
String pName = jsonInst.get("proName").getAsString();
}
Or should I wait for it to be set
if(!pName.isEmpty()){
projectInst.setName(pName)
}
...
Which of these do you think is the best parameter to use for preventing errors.
Is there a way to handle if something is set on a large scale so that I can reduce the amount of code I have to write before I use that varible?
You can create a method that will take field name as parameter and will return json value for that field :
private String getJSONData(String field,JsonObject json){
String data=null;
if(json.has(field)){
data=json.get(field).getAsString();
}
return data;
}
you can call this method for each of your field:
String pId = getJSONData("proId",jsonInst);
By this way you can not only escape NullPointerException, but also avoid code repetition.

Unable to delete object using datastore, query (with `id`) on dao and ds return zero result

I'm trying to delete an object from datastore but it's not deleting it. Code is given below:
MoIADocument moIADoc = new MoIADocument();
// update fields in moIADoc object
ds.save(moIADoc);
printDBDocs();
// create a query to retrieve objects
QueryResults<MoIADocument> foundResults = dao.find(query);
List<MoIADocument> list = foundResults.asList();
for (MoIADocument obj : list) {
ds.delete(obj);
MoDBIATopic topicBO = obj.getData().get(EnumChannelType.FACEBOOK).getData().get(GraphConstants.Topic_Default);
topicBO.setInfluence(topicBO.getInfluence() * 25);
ds.save(obj);
}
printDBDocs();
###########################
the result of first print (in JSON format) is:
###########################
obj in for loop is:
###########################
and after for loop the print statement gives two objects as:
Why is it not deleting old object by mongoConstants.ds.delete(obj);? And I have annotated id field ad #Id but still two objects are saved with same id. How is this possible? How can we force to overwrite an object if id is same?
#Id
#Indexed
private String id;
Note: id is the top level id as indicated in JSON.
And I tried using query as:
Query<MoIADocument> query1 = ds.createQuery(MoIADocument.class).disableValidation();
query1.field("id").equal(obj.getId());
ds.delete(query1);
This too not working as expected.
EDIT:
Problem looks like in query result. Using above query1, it returned zero results.
I tried multiple approaches but nothing worked as expected.. tried following ways:
Approach# 1:
Query<MoDBIADocument> query1 = dao.createQuery(MoDBIADocument.class).disableValidation();
query1.field("id").equal(moDoc.getId());
QueryResults<MoDBIADocument> foundResults1 = dao.find(query1);
printDBDocs(foundResults1);
Approach# 2: (using _id instead of id)
Query<MoDBIADocument> query1 = dao.createQuery(MoDBIADocument.class).disableValidation();
query1.field("_id").equal(moDoc.getId());
QueryResults<MoDBIADocument> foundResults1 = dao.find(query1);
printDBDocs(foundResults1);
Approach# 3:
using `ds` instead of `dao` in `Approach# 1` and `Approach# 2`
Approach# 4:
DBObject dbObj = new BasicDBObject("id", moDoc.getId());
DBCursor cursor = COLLECTION.find(dbObj);
None of above approaches worked.. I think problem is with using top level id field (somehow?)..
Using internal id (of FACEBOOK) worked as expected
query1.field("data.FACEBOOK.id").equal(str);
Problem was using a String id as #Id field. Actually it should be ObjectId id. WIth this change class become as below:
#Entity("Collection_IAGlobals")
public class MoDBIADocument {
#Id
#Indexed
private ObjectId id;
// some more fields
}
and updating as:
QueryResults<MoIADocument> foundResults = dao.find(query);
List<MoIADocument> list = foundResults.asList();
for (MoIADocument obj : list) {
//do modifications in obj
dao.save(obj);
}
this way there is no need to delete old object. It replaces old object with new one (since they are having same id).
Works fine using both ds and dao.
But now, new problem with setting id field. If I set using some string as:
moIADoc.setId(new ObjectId("123456"));
it is resulting into following error:
Exception in thread "main" java.lang.IllegalArgumentException: invalid ObjectId [123456]
at org.bson.types.ObjectId.<init>(ObjectId.java:128)
at org.bson.types.ObjectId.<init>(ObjectId.java:122)
It works fine any of other methods, like:
// don't set id field
//OR
//set using default constructor of ObjectId
moIADoc.setId(new ObjectId());
//OR use other constructors e.g.
moIADoc.setId(new ObjectId(new Date(), 123456));
So, the question is why ObjectId is not taking String argument?

Categories

Resources