Need a strategy to lookup property for dynamically generated dropdown component - java

I need to set the null value string for a dropDownChoice component. The default value for null choice is "Choose One", which is hardcoded in the Wicket AbstractSingleChoice class.
The usual way of overriding this is to define a property resource.
However my DropdownChoice component is dynamically generated at runtime, and added to a panel (which is within a datatable). The DropDownChoice is not specifically referenced in the markup.
I'm looking for suggestions on how to programmatically override the default null value string in this situation. It would be nice if the DropDownChoice constructor had an additional parameter for this.
Do I need to programmatically create a new property resource?
Hope this makes sense.

You can override AbstractSingleSelectChoice.getNullKey() and AbstractSingleSelectChoice.getNullValidKey() in order to make Wicket retrieve a localized resource from a .properties or .xml file that does not have the component id as part of the key. This is documented in this JIRA issue: Open DropDownChoice null value internationalization key
For instance:
DropDownChoice ddc = new DropDownChoice(id, model, choices){
#Override
protected String getNullKey(){ return "customDdcNullValue"; }
#Override
protected String getNullValidKey(){ return "customDdcNullValue"; }
}
Will retrieve the <option>'s text from the customDdcNullValue property.
These methods seem to have been added in version 1.4.4, if you're on 1.3, you could always use an IChoiceRenderer with the DropDownChoice that returns the proper String in the case of null value. Note that you could retrieve it from resources (with getString(), or StringResourceModel), or grab the value from database/cache if necessary. This may depend on how are you already localizing the choices for non-null values.
Also, you could use the source code of AbstractSingleSelectChoice.getDefaultChoice() to roll your own DropDownChoice with this behavior.
UPDATE: Another way of handling this is to provide your own custom value that represents null, or no-choice. Just remember to use setNullValid(false) on the DropDownChoice to prevent null from appearing when there is a selected value, and initialize the ddc's model with your no-selection value when you still don't know its value in order to avoid Wicket provide null in the getDefaultChoice() call.
When defining the value for your no-selection option, pay special attention to this part of AbstractSingleSelectChoice.getDefaultChoice():
// Null is not valid. Is it selected anyway?
if ((selected == null) || getNoSelectionValue().equals(selected) ||
selected.equals(EMPTY_STRING))
{
Take into account that getNoSelectionValue() returns -1, so please do not use -1, or an empty string, as your custom null value. I learnt this the hard way, believe me, it's not pleasing.

You should use localisation feature to achieve it. There is a method org.apache.wicket.resource.loader.IStringResourceLoader.loadStringResource(org.apache.wicket.Component,java.lang.String) which returns a string value to display for a given component. The string will be a resource key, for your case it is the "nullValid" string, IIRC.
So, you can implement your custom resource manager which will pick data from a database instead of .properties files.

Related

Hibernate PostUpdateEvent getState and getOldState order of values

A little backstory. I am working on a java project, using spring data, and i need to log all changes made to all entities and what type of change (event type) it is (eg. INSERT, UPDATE, DELETE) in mongodb, in an automated way.
For this i am using hibernate postEventListeners (PostInsertListener, PostUpdateListener and PostDeleteListener). This was all good, but now a change has been made to the original requirement, and i need to create a few more event types ( for example LOGIN ).
To create the LOGIN event, without completely altering the existing code, i found that i can just have a simple check, to see if the entity that i'm processing is a User and if the only property that is changed is lastLogin.
if (entity instanceof User) {
if(updateEvent.getDirtyProperties().length == 1 && updateEvent.getDirtyProperties()[0] == 8)
history.setEventType(HistoryEvent.LOGIN);
}
updateEvent is an instace of PostUpdateEvent, from the onPostUpdate function.
This is working fine, but my current implementation is not ideal. In hibernate, getState() and getOldState() return and Object[] that contains all the properties of the object that is being updated. getDirtyProperties() returns the an array of indexes, indexes of only the properties which are not the same in the getState and getOldState arrays.
The problem that i have is that the Object[] returned by getState and getOldState contains only the values of the properties, and i can't figure out the order that they are in. For now i just hardcoded the index, but this solution is not ideal, because if i add/remove a property from the User class, the index also gets modified, and i have to find out what the new index is and change it.
My question is, what order are the properties in the Object[], or how can i change my code so that the value is not hardcoded? Is there a way to get a pair, of property value instead of getting just an array of values?
So i actually found the answer on a hibernate forum.
I'l leave the link to give credit to Vlad Mihalcea
Answer here
To get the property names use this:
String[] properties = event.getPersister().getPropertyNames();
Then match the array indexes and you’ll know what property has
changed.

Returning null with Optional.orElseGet() and setting response value

I have a class TeamResponse used to form a JSON response. It has a handful of parameters, and one of them can be optional:
public TeamResponse(Team team, List<TeamSkillTemplateResponse> teamSkillTemplateResponses) {
this.id = team.getId();
this.name = team.getName();
this.department = new DepartmentResponse(team.getDepartment());
this.division = new DivisionResponse(team.getDepartment().getDivision());
this.valueStream = team.getValueStream().map(ValueStreamResponse::new).orElseGet(null);
this.skillTemplate = teamSkillTemplateResponses;
}
I have actually two questions on this one:
1. Is it appropriate to return null in the response, if the value is not present?
2. Is it appropriate to return null THIS way? (method getTeam() returns Optional)
Thank you.
yes it is. json output will be field not being present, or field null; it depends on json framework configuration. both kind of results are ok from json point of view. Difference only matters if talking about partial updates.
no, you should use .orElse(null) not orElseGet (there you are passing a null supplier, not a null result value).
In my opinion it is okay to return null if there is no value. The only other two options I see are not including the missing value at all in the JSON reply or using some default value which signifies the absence of a value.
Leaving out the value completely depends on the library you use for creating the actual JSON. AFAIK it is not possible to do this when using JAXB annotations. If you use Jackson it is possible though (see this answer).
The second option depends on whether there is a suitable default value. I would definitely go for this option if your value is an array. Instead of returning null I would return an empty array as this usually can be processed by clients without any special handling.

JavaFX: Storing null in a SimpleIntegerProperty

I have a SimpleIntegerProperty which should be able to store null. However, this is not possible, as written in the JavaDoc of IntegerProperty:
Note: setting or binding this property to a null value will set the property to "0.0". See setValue(java.lang.Number).
This also applies to other properties, such as LongProperty, FloatProperty, DoubleProperty, and BooleanProperty (but not to StringProperty, which allows null!). Why is this the case? Is there a workaround to store null in these properties?
The IntegerProperty.setValue(java.lang.Number) method is specified in the interfaces WriteableIntegerValue and WriteableValue. The JavaDoc of WriteableIntegerValue, states:
Note: this method should accept null without throwing an exception, setting "0" instead.
If you are looking at the code of the IntegerPropertyBase class, you can also see that the value is actually stored as a primitive int (which never can be null). This is also specified in the JavaFX API of SimpleIntegerProperty:
This class provides a full implementation of a Property wrapping a int value.
Solution:
You can simply circumvent that by using a SimpleObjectProperty<Integer> instead of a SimpleIntegerProperty, as a SimpleObjectProperty allows null values

Struts 2 checkbox : What's the use of the value attribute when the fieldValue can only be true or false?

Why do we need a value attribute as well as a fieldValue attribute in s:checkbox tag, unlike s:textfield, which has only the value attribute ?
Does the s:checkbox tag's fieldValue attribute allow strings other than "true" or "false" ?
In Struts2 in Action (Manning) , it says about the fieldValue attribute
The actual value that’ll be submitted by the checkbox. Maybe true or
false
That is, if I use
<s:checkbox name="wantMoreChocolates" fieldValue="true"/>
then wantMoreChocolate can only be Boolean type in the java class. In that case, why do the docs specify the type of fieldValue to be a String and not Boolean ?
Moreover, about the value property, it says
the value attribute, as with the other UI components, points to the
actual Java-side property to which the component is bound, a Boolean
in this case.
If through "value" we specify the actual property to which the component is bound, then what's the role of the name attribute. Since, the name attribute has to point to a Boolean value, why does it have to use the value attribute to bind it to another boolean ?
Why can't prepopulation occur solely on the basis of the property corresponding to the name attribute
I think I can have a word about this because I have struggled a lot with this topic.
What we can find in official documentation about fieldValue of <s:checkbox> says:
Name fieldValue
Required FALSE
Default TRUE
Evaluated FALSE
Description The actual HTML value attribute of the checkbox.
But it's saying nothing. I suggest to change it to:
With fieldValue, we can submit a String type value into action
class.
It means:
When the string literally is "true" or "false", and the variable in action class is of boolean type, the string is parsed automatically into boolean value to be stored in the boolean type variable.
If we do not define fieldValue at all, the default value "true" of string type is always submitted to the variable, if there is any defined in Action class to hold it.
Note that if we have fieldValue set, but the checkbox is not checked, nothing will be sent to backend, meaning the String type field to receive the checkbox's value will be null.
But, it can do more than that. Let's see a real-world example combining <s:checkbox /> and Struts 2 Action class fields' naming rules.
Imagine I have a list of checkbox, for example, for a list of Users to select, and each checkbox contains its idUser to process. Now if I want to parse more than one idUser to do my task, I can define:
<s:iterator value="listUsers">
<s:checkbox name="userId" id="userId" fieldValue="%{idUser}"
....
</s:iterator>
Now we will receive a list of numbers in my action class, but with same name. Then we define a field of type List<String> or an array to receive all these IDs of users:
private List<String> userId;
with its getter/setter. Then we can do what we want with this list. Remember that if we want to do calculations with them, these numbers must be parsed into Integer/Long/Whatever you like.
Moreover, if we want to submit "YES/NO" or "1/0", or "radiant/dire" in a checkbox(you name it, and now you know what game I play), we can put a simple JavaScript function in the onchange event of this checkbox to monitor its status, or, more simply, parse its value in action class.
If we have:
<s:checkbox id="myCamp" name="myCamp" fieldValue="radiant"></s:checkbox>
And in action class we must have:
String myCampString = null;
if (StringUtils.isBlank(myCamp)){ //myCamp = null, means I am in Dire.
myCampString = "dire";
} else if (myCamp.equalsIgnoreCase("radiant")){ //myCamp = "radiant", means I am in Radiant.
myCampString = "radiant";
}
// then we process myCampString, now it cannot be null.
***************************I am the middle river*******************************
As for value="true"/"false", I think it's a good example where we programmers cannot name things properly and think everyone can understand what we are talking about :). It can have some clearer name like preselected/selectByDefault, etc.
Again, refrencing Struts 2 DOC, we have:
Name value
Required FALSE
Default
Evaluated FALSE
Type String
Description Preset the value of input element.
Actually, it would be better if we put:
value in <s:checkbox> define whether this checkbox should be checked when it is rendered for the first time. (*)
(*) Note that if value changes after it finished loading the page, Struts 2 will not populate the value into <s:checkbox /> to change its status. JavaScript functions are responsible for this part, for example AngularJS.
For example, if I want to create a new User with a form, and by default every user is active when it's created, we can put this:
<s:checkbox name="isActive" id="isActive" value="true"></s:checkbox>
But, when in a form of editing users, we want to make it checked when the user is active, and not to be checked when is not active, we can do this:
<s:checkbox name="isActive" id="isActive" value="%{user.isActive}"
So that's some tips to make it more understandable, although the DOC has made it clear (in the author's way, I think).
in short fieldValue is The actual HTML value attribute of the checkbox and that will be submitted by the check box.Generally we need not to set this value since this is true by default.
On the other hand value parameter will be used to Preset the value of input element.Please go through the Struts2 form tag document to understand how exactly its working
struts-2-form-tags
struts-2-checkbox-tag
Look up the "key" attribute of checkbox. That may be all that you need. If you don't want to use the "key" attribute, read on.
I have found better luck using "value" attribute. I am a bit confused about "fieldValue" myself. I have seen that "fieldValue" can be used for showing the current value, but if you don't have the "value" attribute, the value (after changing on the form) is not sent to the action method.
fieldValue is the value attribute of checkbox that will be submitted by the check box.
fieldValue can be String, boolean (true/false) etc depending upon your requirement. For more info have a glance at this link http://www.mkyong.com/struts2/struts-2-scheckbox-checkbox-example/

DropDownChoice - nothing selected, value -1?

I have a DropDownChoice component on my Form and when the form is submitted and nothing is selected from the DropDownChoice, the default value that's returned is "-1". Is there are a way to change this behavior?
This behavior is controlled by a constant field
protected static final String NO_SELECTION_VALUE = "-1";
in AbstractSingleSelectChoice, which is a superclass of DropDownChoice.
You can't change this value in a subclass, so in order to change the value used, you would have to locate uses of this constant and override the methods that use it to use some other default.
Doing that would be risky, though it's likely possible. I know you'd have to override at least getDefaultChoice(final Object selected) and getModelValue().
Why do you wish to do this? It's a sensible value for its purpose.
Perhaps there's a better approach to accomplishing your underlying need.
Hook to the beforeSubmit, and change what you want.
I think it is good to have such a value, Since first element is 0, notting means -1.

Categories