I am trying to insert object into Firestore using Android Studio, it gives an error message:
java.lang.IllegalArgumentException: Invalid data. Unsupported type: java.math.BigDecimal
How can I insert BigDecimal into Firestore?
Check Firestore's supported types. If you need anything else, convert to a supported type, then convert back when you read. Typically, you'd use String for BigDecimal. If you need comparisons, zero-pad to your theoretical maximum, or store in another field as Double.
You could do something like this (in Kotlin):
class Model() {
#get:PropertyName("value")
#set:PropertyName("value")
var firestoreValue: String = "0"
var value: BigDecimal
#Exclude get() = firestoreValue.toBigDecimal()
#Exclude set(value) { firestoreValue = value.toPlainString() }
}
Haven't found a better solution so far. Would be nice if it was possible to implement converters (like TypeAdapters for Gson) for unsupported types.
Related
I'm trying to create a feed management system. I have created a simple get and post request for the servlet. I'm able to store the data in the datastore successfully as milliseconds.
But when I retrieve it
long milliseconds = entity.getProperty("timestamp");
I get some error like this
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long
What will be the reason for this issue?
Well, apparently in
long milliseconds = entity.getProperty("timestamp");
entity returns a String, which you assign to a long. This requires a typecast.
Note that Entity (or its superclass, PropertyContainer) explicitly states
The value returned may not be the same type as originally set via setProperty
So - what to do? If you know that you're getting a String, and you want to interpret it as a long: Use the proper conversion method (which is not a typecast).
long longValue = Long.parseLong(stringValue);
...but prepare for NumberFormatExceptions in cases where you convert actual, non-numeric Strings.
Apparently, you are trying to retrieve a String of number format which you want to cast to a long value. The first thing you will have to do is to check whether the value obtained from entity.getProperty("timestamp") returns a number. There's is a special library called Apache Commons Lang 3 that allows to check if your string is of numeric format. If it's the case, then it's a simple implicit cast to long value that you should do. Your code should look as follows,ASSUMING ENTITY IS NOT NULL:
import org.apache.commons.lang3.math.NumberUtils;
if(NumberUtils.isCreatable(entity.getProperty("timestamp")){
long milliseconds = Long.parseLong(entity.getProperty("timestamp"));
}
else{
//print the information you want to identify the value of the property
//for example:
System.out.println("The following value cannot be parsed to long : " +
entity.getProperty("timestamp"));
}
I am performing something like this for using right join in the spark application in java.
Dataset<Row> dataset3 = dataset1.join(dataset2,
(Seq<String>) dataset1.col("target_guid"),RightOuter.sql());
But getting this error
java.lang.ClassCastException: org.apache.spark.sql.Column cannot be
cast to scala.collection.Seq
Other than this, I couldn't find the way to use joins in java for the datasets.
Could anyone help me finding a way to do this?
If you wanted to use below dataset api in java-
def join(right: Dataset[_], usingColumns: Seq[String], joinType: String): DataFrame
then convert the string list into seq. Please keep below method handy to convert java list to scala seq as most of the spark apis accept scala seq
import scala.collection.JavaConversions;
<T> Buffer<T> toScalaSeq(List<T> list) {
return JavaConversions.asScalaBuffer(list);
}
Also you can't use joinType as RightOuter.sql() which evaluates to 'RIGHT OUTER'. The supported join types includes -
'inner', 'outer', 'full', 'fullouter', 'full_outer', 'leftouter', 'left', 'left_outer', 'rightouter', 'right', 'right_outer', 'leftsemi', 'left_semi', 'leftanti', 'left_anti', 'cross'
Now you can use-
Dataset<Row> dataset3 = dataset1.join(dataset2,
toScalaSeq(Arrays.asList("target_guid")), "rightouter");
Can change your code to something like this,
Dataset<Row> dataset3 = dataset1.as("dataset1").join(dataset2.as("dataset2"),
dataset1.col("target_guid").equalTo(dataset2.col("target_guid")), RightOuter.sql());
I have the following POJO:
public class Order {
private String name;
private String status;
private BigDecimal total;
// getters, setters and ctors down here
}
I am looping through a List<Order> and trying to update all their status fields to a value of "ORDERED". The old (pre Streaming API) way of doing this was:
for (Order order : orders) {
order.setStatus("ORDERED");
}
I'm trying to figure out the Java 8 ("Streaming") way of accomplishing the same thing. My best attempt thus far:
orders.stream().map(order -> order.setStatus("H"));
Produces a compiler error:
"Incompatible types. Required List but 'map' was inferred to Stream: no instance(s) of type variable(s) R exist so that Stream conforms to List"
Any ideas where I'm going awry?
Use forEach:
orders.forEach(order -> order.setStatus("H"));
You do not want to use Stream.map() because it requires a return value which replaces the original value in the stream. You are also missing a terminal operation in your stream, so even if you fix that by returning the original value it wont work. Stream.forEach() is a terminal operation you can use for this.
To update each object in your list you can just use orders.forEach(). This is the same as orders.stream().forEach().
orders.forEach(o -> o.setStatus("H"));
If you want to update only some values of your List you can use Stream.filter() before:
orders.stream()
.filter(o -> "ABC".equals(o.getName())
.forEach(o -> o.setStatus("H"));
I am using jayway JsonPath, Suppose I have Json like this:
jsonObject:
{
"balance": 50000000000000.0
}
jspath: $.balance
val response =JsonPath.parse(jsonObject).read(jsPath).toString
println("response: ", response )
here I am getting value as "response: 5.0E7" but I want it as "50000000000000.0"
I know how to convert from double to string. But my case is I have to call external Rest API and I will get json as response, based on jspath it has to fetch original value. It means the same code has to work for string, integer and double types with its original content, but not to its specific content format.
{
"balance": "50000000000000.0" (here balance is string)
}
expected: 50000000000000.0 result: 50000000000000.0
{
"balance": 50000000000000.00 (here balance is double)
}
expected: 50000000000000.0 result: 5.0E7(but I need 50000000000000.0)
The same code it has to work for both scenarios or is there any other library to get this solution or is there any chance of getting return type from read(), so using exception handling I can handle that.
Since you use Scala you can simply read value as Any and format it using pattern matching, e.g.:
val response: Any = JsonPath.parse(jsonObject).read(jsPath)
val formattedResponse = response match {
case d: Double => d.formatted("%f")
case _ => response.toString
}
Alternatively you can configure Jayway JsonPath to always parse floating numbers as BigDecimal, whose toString in most cases will print value without exponents (unless it's really small fraction (~ <1e-6), which anyway would be more readable with exponent) and has additional advantage of being capable of storing longer numbers without losing precision. This would however require configuring JsonPath with JsonProvider that always uses BigDecimal (default SmartJson can't do that, Jackson will work fine).
I have a field called phone number which has values such as 0833888999 that I want to format as following 0833 888 999.
The answer that Rachana offered blew is true for few countries but not all countries.
Therefore,
I am using this Google library to format contact numbers from different countries; however, the problem is that after persisting the contact numbers in database I can not search for them on database, for example the library would format contact numbers of different countries in different format, for example add space or "-" between them that makes hibernate unable to find them.
+18182223333 >>> +1 818-222-3333
+441135558888 >>> +44 113 555 8888
Hibernate
.add(Restrictions.ilike("user.phone","+18182223333");
Try this
<s:property value="getText('{0,number,0### ### ###}',{phone})"/>
Where,phone=0833888999
Hope this will help you also see Using Struts2 Tags to Formatting Numbers
you will get clear idea about number formatting
I think you should keep the raw phone number (e.g. 0833888999) in the database and it's the View responsibility to format it accordingly.
You can have a separate table "country_phone_format" holding a country_id and a phone_format and you could fetch the phone_format as a #ManyToOne entity so that you have both the raw data and the format to properly display it into the View.
The PhoneFormat could be easily cached with the second level cache, as they should be rarely modified.
Just as Vlad mentions, you should keep the raw phone number (e.g. 0833888999) in the database (or save it with the country and area code if you prefer) and leave th responsibility to format it accordingly to the View.
You can use Type Conversion to convert to/from the format you desire - and take advantage of the google library you mention. Something like the following can get you started (abbreviated just to get the gist of it):
public class MyConverter extends StrutsTypeConverter {
public Object convertFromString(Map context, String[] values, Class toClass) {
String phoneNr = values[0]
MyPhoneObject phone = googleLibrary.doYourMagic(phoneNr);
return phone;
}
public String convertToString(Map context, Object o) {
googleLibrary.parseString( ((MyPhoneObject)o).rawPhoneNr() );
}
}
Don't forget to register the converter in xwork-conversion.properties
my.PhoneObject=path.to.MyConverter