I'm trying to pass a payload to a validate(ValidationPayload) in the Play Framework using Java. I can not access the values stored in payload.getAttrs() which returns a TypedMap.
I tried to access the Cookies by calling in the validate method payload.getAttrs().getOptional(TypedKey.create("Cookies")) but I always get a null back.
When I evaluate expression using IntelliJ I see the attrs contain Cookies, Flash and more. But I can not access theses values. I can see the values in the Expression Evaluator screenshot
public String validate(Constraints.ValidationPayload payload) {
TypedMap attrs = payload.getAttrs();
Optional<Object> baseDomain = payload.getAttrs().getOptional(TypedKey.create("baseDomain"));
Locale value = payload.getAttrs().get(TypedKey.create("selectedLang"));
return "String";
}
How can I access these objects stored in a TypedMap?
I figured this out a TypedMap map uses TypedKeys. A typed key is unique to each INSTANCE of the key.
That means you need to fetch from the typedMap with the same instance of the key that was used to put in the map. Creating a new key will cause an empty or null response.
This should work:
TypedKey<String> baseDomainKey = TypedKey.create("baseDomain")
payload.getAttrs().addAttrs(baseDomainKey, "domain")
String domain = payload.getAttrs().get(baseDomainKey)
This will not work however:
TypedKey<String> baseDomainKey = TypedKey.create("baseDomain")
payload.getAttrs().addAttrs(baseDomainKey, "domain")
String domain = payload.getAttrs().get(TypedKey.create("baseDomain"))
Related
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)
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.
in my method I have let's say UserDetails object which has some defined value like id, phone etc.
User changing only one value through form, it's email. Is the way how I could use method
userDetailsForm.bindFromRequest(new String[]{"email"}).get()
to not 'loose' previous values? The above example give me new userDetail object with only defined email field. Of course I know that I can use DynamicForm class, or just
userDetailsForm.bindFromRequest().get().getEmail()
but it would be helpfull to have method which does all this binding in one line.
=========EDIT
DynamicForm dynamicForm = Form.form().bindFromRequest();
String email = dynamicForm.get("email");
isn't that what I'm looking for.
=========EDIT======================================
In other words, I want to divide my form to 3 steps, but after every step I am doing update on DB. So for example when I am POSTing step2 I have object with values from previous step:
User [userId=8, createdById=12, name=null, active=false, country=EN]
so now when I am doing:
static Form<User> userForm = Form.form(User.class);
User user = User.find(8);
User user2 = (User) userForm.fill(user).bindFromRequest("name").get();
I am geting new object with empty fields:
User [userId=0, createdById=0, name="value from step 2", active=false, country=null]
I will be very greatfull for any advise.
Try this
Form<UserDetail> submittedForm = form(UserDetail.class).bindFromRequest();
String emailID = submittedForm.data().get("email");
data() will hold name and value pair like following Map<String, String>, further retrieve value by providing its key name inside get() will return you the desired value.
Ok guys, I've figured out how to solve problem.
Here is discussion about this:
https://groups.google.com/forum/#!searchin/play-framework/Form$20bind/play-framework/MtjBV5YNQ3E/QumAmLbMl5sJ
one of possible solution is here:
https://gist.github.com/nraychaudhuri/10590943
import com.fasterxml.jackson.databind.ObjectMapper;
private static Form<Computer> editableForm(final Computer obj) {
ObjectMapper mapper = new ObjectMapper();
Form<Computer> form = Form.form(Computer.class);
Map<String,String> data = mapper.convertValue(obj, Map.class);
Map<String, String> submittedData = form.bindFromRequest().data();
data.putAll(submittedData);
return form.bind(data);
}
and my solution is below:
public T bind(T target, Map<String, String> newValues) {
DataBinder binder = new DataBinder(target);
binder.setAllowedFields(getAllowedFields());
binder.bind(new MutablePropertyValues(newValues));
return target;
}
=================EDIT
Here is important disscussion about security issue: https://groups.google.com/forum/#!searchin/play-framework/Form$20bind/play-framework/uGrSlJMo48c/QnVjzP4ovqcJ
Form.bindFromRequest
without arguments. However, as probably most of you know, invoking
that method without parameters will bind all fields of the
corresponding model object to like-named request parameters, including
fields holding internal state that must never be set from the outside
(e.g. boolean isAuthenticated). That is, an attacker may set any field
and circumvent security if they only know the name of the
corresponding model object field. This is of course a catastrophic
security vulnerability (similar to PHP's notorious and deprecated
register_globals option:
http://www.php.net/manual/en/security.globals.php).
I am working on something which fetches data from database and constructs protobuff message. Given the possibility that null values can be fetched from the database for certain fields , I will get Null-pointer exception while trying to construct the protobuff message. Getting to know that null is not supported in protobuffs from the thread http://code.google.com/p/protobuf/issues/detail?id=57, I am wondering whether the only other way to handle NPE getting thrown is to insert manual checks into the java file corresponding to the proto like below!
message ProtoPerson{
optional string firstName = 1;
optional string lastName = 2;
optional string address1 = 3;
}
ProtoPerson.Builder builder = ProtoPerson.Builder.newBuilder();
if (p.getFirstName() != null) builder.setFirstName(p.getFirstName());
if (p.getLastName() != null) builder.setLastName(p.getLastName());
if (p.getAddress1() != null) builder.setAddress1(p.getAddress1());
...
So can someone please clarify whether there is any other possible efficient way to handle the null values during protobuff construction??
Disclaimer: Answer from a Googler using protobufs on a daily basis. I'm by no means representing Google in any way.
Name your proto Person instead of PersonProto or ProtoPerson. Compiled protobufs are just class definitions specified by the language you are using, with some improvements. Adding "Proto" is extra verbosity.
Use YourMessage.hasYourField() instead of YourMessage.getYourField() != null. Default value for protobuf string is an empty string, which does NOT equal to null. Whereas, no matter whether your field is unset or cleared or empty string, .hasYourField() always returns false. See default values for common protobuf field types.
You've probably known, but I wanna say explicitly: Don't programmatically set a protobuf field to null. Even for outside of protobuf, null causes all sorts of problems. Use .clearYourField() instead.
Person.Builder class does NOT have a .newBuilder() method. Person class does. Understand the Builder Pattern like this: You create a new builder only if you do not have it yet.
A rewrite of your protobuf:
message Person {
optional string first_name = 1;
optional string last_name = 2;
optional string address_1 = 3;
}
A rewrite of your logic:
Person thatPerson = Person.newBuilder()
.setFirstName("Aaa")
.setLastName("Bbb")
.setAddress1("Ccc")
.build();
Person.Builder thisPersonBuilder = Person.newBuilder()
if (thatPerson.hasFirstName()) {
thisPersonBuilder.setFirstName(thatPerson.getFirstName());
}
if (thatPerson.hasLastName()) {
thisPersonBuilder.setLastName(thatPerson.getLastName());
}
if (thatPerson.hasAddress1()) {
thisPersonBuilder.setAddress1(thatPerson.getAddress1());
}
Person thisPerson = thisPersonBuilder.build();
And if thatPerson is a person object that you created that has attribute values that could be an empty string, empty spaces or null, then I'd recommend using Guava's Strings library:
import static com.google.common.base.Strings.nullToEmpty;
Person.Builder thisPersonBuilder = Person.newBuilder()
if (!nullToEmpty(thatPerson.getFirstName()).trim().isEmpty()) {
thisPersonBuilder.setFirstName(thatPerson.getFirstName());
}
if (!nullToEmpty(thatPerson.hasLastName()).trim().isEmpty()) {
thisPersonBuilder.setLastName(thatPerson.getLastName());
}
if (!nullToEmpty(thatPerson.hasAddress1()).trim().isEmpty()) {
thisPersonBuilder.setAddress1(thatPerson.getAddress1());
}
Person thisPerson = thisPersonBuilder.build();
Proto 3
wrappers.proto supports nullable values:
string(StringValue),
int(Int32Value),
bool(BoolValue)
and etc
Example
syntax = "proto3";
import "google/protobuf/wrappers.proto";
message ProtoPerson {
google.protobuf.StringValue firstName = 1;
google.protobuf.StringValue lastName = 2;
google.protobuf.StringValue address1 = 3;
google.protobuf.Int32Value age = 4;
}
There's no easy solution to this. I'd recommend just dealing with the null checks. But if you really want to get rid of them, here are a couple ideas:
You could write a code generator plugin which adds setOrClearFoo() methods to each Java class. The Java code generator provides insertion points for this (see the end of that page).
You could use Java reflection to iterate over the get*() methods of p, call each one, check for null, and then call the set*() method of builder if non-null. This will have the added advantage that you won't have to update your copy code every time you add a new field, but it will be much slower than writing code that copies each field explicitly.
I have a task where object properties need to be populated from data received via JSON web service. The property names are mapped to the JSON keys. I am using the following code in an attempt to populate the object but the app crashes when it hits this line:
while(looper.hasNext()){
String key = looper.next();
String val = json.get(key).toString();
user.getClass().getDeclaredField(key).set(user, val); // crash
}
The object is called user. I have verified that the key variable does match a property in the user object. Any ideas on how to fix this? THanks!
you should set your field accessible
Field field = user.getClass().getDeclaredField(key);
if (field != null) {
field.setAccessible(true);
field.set(user, val);
}