I wrote a code in java to create a Olingo Odata client V4. I am able to send queries and receive a response and extract each elements. I want to go further and make some calculations with data I receive:
-I would like to know if it is possible in java to map data I received into a class.
-I am wondering if it is possible to cast data into String, Integer, Long, Double in another way I did below:
public List<ItemSales> getItemSale(ClientEntitySetIterator<ClientEntitySet, ClientEntity> iteratorItemSales)
{
List<ItemSales> itemSalesList = new ArrayList<ItemSales>();
while (iteratorItemSales.hasNext()) {
ClientEntity resultsIterator = iteratorItemSales.next();
List<ClientProperty> properties = resultsIterator.getProperties();
ItemSales itemsales = new ItemSales();
//EdmCast
for (ClientProperty property : properties)
{
switch( property.getName().toLowerCase())
{
case "id": itemsales.setId(Long.parseLong(property.getValue().toString())); break;
}
ClientValue value =property.getValue();
}
}
return itemSalesList;
}
Indeed, once I get in my example, I want to get a long value. Nevertheless all elements of the list I got are in "ClientValue" format.
Related
I have a JSON response like this:
{
"AED_BDT": 23.100486
}
But the key changes according to my query like if my query is USD_BDT, then it will give response like this:
{
"USD_BDT": 23.100486
}
So,that means I need to change the JSON key according to my query. But I couldn't find any solution on how to do this.
I tried by converting the response body into String and then replaced the Key according to my query, but this is not working..
This is my model class:
data class ResponseCurrencyConvert(
val USD_BDT: Double
)
This is what I tried so far:
val params = HashMap<String,String>()
params["compact"]="ultra"
params["apiKey"]= API_KEY
params["q"]="${currencyFrom}_${currencyTo}"//getting specific currencies and then setting them as query,i.e:USD_BDT
message(TAG,"Query: ${params["q"]}")
prefManager.query=params["q"]!!
//calling the API
apiServices.convertCurrency(params).enqueue(object : Callback<ResponseCurrencyConvert>{
override fun onFailure(call: Call<ResponseCurrencyConvert>, t: Throwable) {
message(TAG,"onFailure: ${t.localizedMessage}")
}
override fun onResponse(call: Call<ResponseCurrencyConvert>, response: Response<ResponseCurrencyConvert>) {
message(TAG,"onResponse Code: ${response.code()}")
message(TAG,"onResponse Body: ${Gson().toJson(response.body())}")
val json = Gson().toJson(response.body())//converting the response as string
val oldValue = "USD_BDT"//the key which was in my model class
val newValue=params["q"]// the new key which is my query
val output = json.replace(oldValue,newValue!!,false) // replacing the default query with my query
val newResponse = Gson().fromJson(output,ResponseCurrencyConvert::class.java)//again converting the new replaced string to json
if (response.isSuccessful){
message(TAG,"Output: $output")
message(TAG,"onResponse Result: ${newResponse?.USD_BDT}")
message(TAG,"onResponse newResult: ${newResponse.USD_BDT}")
rate= newResponse?.USD_BDT//getting the value; this is returning 0 every time expect when my query is USD_BDT
I commented everything that I did on the code, please read that carefully. Your help is highly appreciated..
Keys are defined from the server only I guess
The best way you can do is like keep both keys and make it nullable
else you have an alternate name in JSON parsing
A way to do that is maintaining the 2 different keys, which is the most simple and effective.
Another way to accomplish this is changing the Response type to string. When you get the response you change the JSON string, changing the key name and then use GSON to manually convert from JSON to Object.
Maybe it can be done also with a Custom Json Converter, but I don't think is worth.
If the key changes for every other response, I would suggest using HashMap<String, String>. Instead of mapping directly to String value which changes dynamically using HashMap would solve your issue.
Let me know how it goes.
I want to get value floor from the Google Fit. But I not found about data type of floor.
This is my code.
private void setDailyFloors() {
PendingResult<DailyTotalResult> dailyFloors = Fitness.HistoryApi.readDailyTotal(mClient, DataType.TYPE_ACTIVITY_SAMPLE);
dailyFloors.setResultCallback(new ResultCallback<DailyTotalResult>() {
#Override
public void onResult(#NonNull DailyTotalResult dailyTotalResult) {
if (dailyTotalResult.getStatus().isSuccess()) {
DataSet totalSet = dailyTotalResult.getTotal();
if (totalSet != null) {
floor = totalSet.isEmpty() ? 0 : totalSet.getDataPoints().get(0).getValue(Field.FIELD_ACTIVITY).asInt();
}
}
}
});
}
I don't see any related to a Data Type Floor in the Google Fit documentation, maybe this one is a custom data type.
Just check this link to know more about Custom data types.
To create a custom data type for the first time, use the ConfigApi.createCustomDataType method:
// 1. Build a request to create a new data type
DataTypeCreateRequest request = new DataTypeCreateRequest.Builder()
// The prefix of your data type name must match your app's package name
.setName("com.app.custom_data_type")
// Add some custom fields, both int and float
.addField("field1", Field.FORMAT_INT32)
.addField("field2", Field.FORMAT_FLOAT)
// Add some common fields
.addField(Field.FIELD_ACTIVITY)
.build();
// 2. Invoke the Config API with:
// - The Google API client object
// - The create data type request
PendingResult<DataTypeResult> pendingResult =
ConfigApi.createCustomDataType(mClient, request);
// 3. Check the result asynchronously
// (The result may not be immediately available)
pendingResult.setResultCallback(
new ResultCallback<DataTypeResult>() {
#Override
public void onResult(DataTypeResult dataTypeResult) {
// Retrieve the created data type
DataType customType = dataTypeResult.getDataType();
// Use this custom data type to insert data in your app
// (see other examples)
...
}
}
);
Just read the above links to know more about it. Including the, How to
Retrieve your custom data types and How to Create data points of custom data types.
I use querydsl to query on a mongodb. As allowed by mongodb, in several cases I store objects of different types in the same collection.
For instance, in my data model I have:
interface Notification {
NotificationType getType(); // EMAIL, SMS etc.
}
interface EmailNotification extends Notification {
Set<User> getRecipients();
}
Now I want to query for Notifications of any kind (not only EmailNotification), but in the case I have EmailNotifications, I want to filter on some recipient.
I tried this code (doesn't work):
final QNotification notification = QNotification.notification;
final BooleanBuilder typesPredicate = new BooleanBuilder();
// "recipientEmails" and "recipientPhones" are provided parameters (lists of String)
typesPredicate.or(notification.type.eq(NotificationType.EMAIL)
.and(notification.as(QEmailNotification.class).recipients
.any().email.in(recipientEmails)));
typesPredicate.or(notification.type.eq(NotificationType.SMS)
.and(notification.as(QSMSNotification.class).recipients
.any().phoneNumber.in(recipientPhones)));
notificationPersister.query(Notification.class).where(typesPredicate);
It doesn't throw any error or exception, but I don't get the expected result (actually I don't get any result) because the generated mongo query is wrong, and I can't get how to make it right.
Generated query is like:
{
"$and":[
// ...
{
"$or":[
{
"type":"EMAIL",
"notification.recipients.email":{
"$in":[
"a#b.com"
]
}
},
// ...
]
}
]
}
And the issue lies in the key "notification.recipients.email": it should be just "recipients.email".
Why does "notification.as(QEmailNotification.class).recipients" translates to "notification.recipients", and how can I make it as expected ?
Note that the following would work:
notificationPersister.query(EmailNotification.class).where(
QEmailNotification.eMailNotification.recipients.any().email.in(recipientEmails));
But then I'm forced to run 1 query per inherited class, which is not efficient.
As Timo said: Fixed in querydsl via github.com/querydsl/querydsl/pull/1428
I'm trying to make sure my Jersey request parameters are sanitized.
When processing a Jersey GET request, do I need to filter non String types?
For example, if the parameter submitted is an integer are both option 1 (getIntData) and option 2 (getStringData) hacker safe? What about a JSON PUT request, is my ESAPI implementation enough, or do I need to validate each data parameter after it is mapped? Could it be validated before it is mapped?
Jersey Rest Example Class:
public class RestExample {
//Option 1 Submit data as an Integer
//Jersey throws an internal server error if the type is not Integer
//Is that a valid way to validate the data?
//Integer Data, not filtered
#Path("/data/int/{data}/")
#GET
#Produces(MediaType.TEXT_HTML)
public Response getIntData(#PathParam("data") Integer data){
return Response.ok("You entered:" + data).build();
}
//Option 2 Submit data as a String, then validate it and cast it to an Integer
//String Data, filtered
#Path("/data/string/{data}/")
#GET
#Produces(MediaType.TEXT_HTML)
public Response getStringData(#PathParam("data") String data) {
data = ESAPI.encoder().canonicalize(data);
if (ESAPI.validator().isValidInteger("data", data, 0, 999999, false))
{
int intData = Integer.parseInt(data);
return Response.ok("You entered:" + intData).build();
}
return Response.status(404).entity("404 Not Found").build();
}
//JSON data, HTML encoded
#Path("/post/{requestid}")
#POST
#Consumes({MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON})
#Produces(MediaType.TEXT_HTML)
public Response postData(String json) {
json = ESAPI.encoder().canonicalize(json);
json = ESAPI.encoder().encodeForHTML(json);
//Is there a way to iterate through each JSON KeyValue and filter here?
ObjectMapper mapper = new ObjectMapper();
DataMap dm = new DataMap();
try {
dm = mapper.readValue(json, DataMap.class);
} catch (Exception e) {
e.printStackTrace();
}
//Do we need to validate each DataMap object value and is there a dynamic way to do it?
if (ESAPI.validator().isValidInput("strData", dm.strData, "HTTPParameterValue", 25, false, true))
{
//Is Integer validation needed or will the thrown exception be good enough?
return Response.ok("You entered:" + dm.strData + " and " + dm.intData).build();
}
return Response.status(404).entity("404 Not Found").build();
}
}
Data Map Class:
public class DataMap {
public DataMap(){}
String strData;
Integer intData;
}
The short answer is yes, though by "filter" I interpret it as "validate," because no amount of "filtering" will EVER provide you with SAFE data. You can still run into integer overflows in Java, and while those may not have immediate security concerns, they could still put parts of your application in an unplanned for state, and hacking is all about perturbing the system in ways you can control.
You packed waaaaay too many questions into one "question," but here we go:
First off, the lines
json = ESAPI.encoder().canonicalize(json);
json = ESAPI.encoder().encodeForHTML(json);
Aren't doing what you think they're doing. If your JSON is coming in as a raw String right here, these two calls are going to be applying mass rules across the entire string, when you really need to handle these with more surgical precision, which you seem to at least be subconsciously aware of in the next question.
//Is there a way to iterate through each JSON KeyValue and filter
here?
Partial duplicate of this question.
While you're in the loop discussed here, you can perform any data transformations you want, but what you should really be considering is using the JSONObject class referenced in that first link. Then you'll have JSON parsed into an object where you'll have better access to JSON key/value pairs.
//Do we need to validate each DataMap object value and is there a
dynamic way to do it?
Yes, we validate everything that comes from a user. All users are assumed to be trained hackers, and smarter than you. However if you handled filtering before you do your data mapping transformation, you don't need to do it a second time. Doing it dynamically?
Something like:
JSONObject json = new JSONObject(s);
Iterator iterator = json.keys();
while( iterator.hasNext() ){
String data = iterator.next();
//filter and or business logic
}
^^That syntax is skipping typechecks but it should get you where you need to go.
/Is Integer validation needed or will the thrown exception be good
enough?
I don't see where you're throwing an exception with these lines of code:
if (ESAPI.validator().isValidInput("strData", dm.strData, "HTTPParameterValue", 25, false, true))
{
//Is Integer validation needed or will the thrown exception be good enough?
return Response.ok("You entered:" + dm.strData + " and " + dm.intData).build();
}
Firstly, in java we have autoboxing which means this:
int foo = 555555;
String bar = "";
//the code
foo + bar;
Will be cast to a string in any instance. The compiler will promote the int to an Integer and then silently call the Integer.toString() method. Also, in your Response.ok( String ); call, THIS is where you're going to want to encodeForHTML or whatever the output context may be. Encoding methods are ALWAYS For outputting data to user, whereas canonicalize you want to call when receiving data. Finally, in this segment of code we also have an error where you're assuming that you're dealing with an HTTPParameter. NOT at this point in the code. You'll validate http Parameters in instances where you're calling request.getParameter("id"): where id isn't a large blob of data like an entire JSON response or an entire XML response. At this point you should be validating for things like "SafeString"
Usually there are parsing libraries in Java that can at least get you to the level of Java objects, but on the validation side you're always going to be running through every item and punting whatever might be malicious.
As a final note, while coding, keep these principles in mind your code will be cleaner and your thought process much more focused:
user input is NEVER safe. (Yes, even if you've run it through an XSS filter.)
Use validate and canonicalize methods whenever RECEIVING data, and encode methods whenever transferring data to a different context, where context is defined as "Html field. Http attribute. Javascript input, etc...)
Instead of using the method isValidInput() I'd suggest using getValidInput() because it will call canonicalize for you, making you have to provide one less call.
Encode ANY time your data is going to be passed to another dynamic language, like SQL, groovy, Perl, or javascript.
var catids = new Array();
I have a catids array where i store the checked checkbox values like the below one.
cat = $("input[name=catChkBox]:checked").map(function () {
return $(this).data('name');
}).get().join(",");
the cat variable forms something like this 1,2,3..
I want to send this "cat" to a java method and print those values.
I pass the values to java through a dwr call like this
DataHandler.getTasks( categories, {callback:function(data){
}, errorHandler:function(){
},async:false
});
I have configured dwr for pojo. should I configure anything for parameters?
I tried the below code but I didn't get anything.
public List<Facade> getTasks(String myIds){
String[] ids = catids .split(",");
System.out.println("-------size of cat id------------" + myIds.length);
for (int i=0; i<myIds.length;i++)
System.out.println(myIds[i]);
//finally it will return a pojo which i l be receiving it in data of dwr call.
-------size of cat id------------ is 1
myIds[i] prints nothing
I need it as an integer back.
What mistake am I doing ?
I will do it in this way.
JavaScript creates json object like this {"categoryIds": [1,2,3,4,5]}
Java converter convert json to java POJO object using for example Gson or Jackson library.
After convert you can work with java POJO object which have list of categories.
If you use this solution your code will be more clear and you will be able to share more objects between JavaScript and Java using the same clear solution.
Example (pseudo code)
CategorList class
public class CategoryList {
private ArrayList<Category> categoryList;
// getters and setters
}
Converter
public class CategoryListConverter {
public CategoryList convert(String json) {
Gson g = new Gson();
CategoryList cl = g.fromJson(json, CategoryList.class);
return cl;
}
}
I tried the code it workd fine
getTasks("1,2,3");
check what the value of categoriesIds is sent to getTask
Send this as a form parameter from webpage. Then get this from HttpServletRequest request object in java.
request.getParameter('categoryId');