I have a Wicket Textfield which contains an Integer value
currentValueTextField = new TextField<IntParameter>("valueText", new PropertyModel<IntParameter>(model, "value"));
I'm attaching a custom validator to this, as follows
currentValueTextField.add(new IntegerValidator());
The validator class is
class IntegerValidator extends AbstractValidator<IntParameter> {
private static final long serialVersionUID = 5899174401360212883L;
public IntegerValidator() {
}
#Override
public void onValidate(IValidatable<IntParameter> validatable) {
ValidationError error = new ValidationError();
if (model.getValue() == null) {
AttributeAppender redOutline = new AttributeAppender("style", new Model<String>("border-style:solid; border-color:#f86b5c; border-width: 3px"), ";");
currentValueTextField.add(redOutline);
currentValueTextField.getParent().getParent().add(redOutline);
validatable.error(error);
}
}
}
However if I type nothing in the textfield, my onValidate() method is not being called.
What is the recommended way to check for null values in this case?
I would also like to do range checking on the value entered.
just call
currentValueTextField.setRequired(true);
to mark the field as required and have Wicket handle null values on it's own. You can easily combine multiple validators per input field.
Any special error handling, like adding red borders or displaying of error messages can be implemented in the onError method of the form or by adding FeedbackBorders to the appropriate fields.
Override validateOnNullValue() that is false by default.
#Override
public boolean validateOnNullValue()
{
return true;
}
This is the description of validateOnNullValue() method:
Indicates whether or not to validate the value if it is null. It is usually desirable to skip validation if the value is null, unless we want to make sure
the value is in fact null (a rare use case). Validators that extend this and
wish to ensure the value is null should override this method and return
true.
currentValueTextField.setRequired(true);
Now you need to customise the error message. So subclass FeedbackPanel.
you can find more information in the following link
Add this class to your form or component
A better (and reusable) way to do this is to override the isEnabled(Component) method of the behavior:
public class HomePage extends WebPage {
private Integer value;
public HomePage() {
add(new FeedbackPanel("feedback"));
add(new Form("form", new CompoundPropertyModel(this))
.add(new TextField("value")
.setRequired(true)
.add(new ErrorDecorationBehavior()))
.add(new Button("submit") {
#Override
public void onSubmit() {
info(value.toString());
}
}));
}
}
class ErrorDecorationBehavior extends AttributeAppender {
public ErrorDecorationBehavior() {
super("style", true, Model.of("border-style:solid; border-color:#f86b5c; border-width: 3px"), ",");
}
#Override
public boolean isEnabled(Component component) {
return super.isEnabled(component) && component.hasErrorMessage();
}
}
Related
Say I have a function that looks at a file and returns two results: recognized and unrecognized. When it returns the recognized result, I want the result to also contain a message but when it is unrecognized, no message is necessary.
public Result checkFile(File file) {
...
}
There are two ways I can think of to accomplish this...
Have the Result class like so:
class Result {
private Type type;
private String message;
enum Type {
RECOGNIZED, UNRECOGNIZED
}
}
Or do it like so:
class Result {
}
class Unrecognized extends Result {
}
class Recognized extends Result {
private String message;
}
I'm inclined to use the second method, even though I'd have to check the result using instanceof and I've read that instanceof should be avoided whenever possible, but doing this avoids having a null message when the result is unrecognized. For this example a null message wouldn't be much of an issue, but what if there is a lot more data associated with a recognized result? It seems like worse practice to me to instantiate a class that could have all null fields.
What is the best practice to handle this situation? Is there some standard method or pattern?
Two classes might be overkill, because of it being one and the same class of object. Also an enum with two values which merely reassemble true and false is not required. One class Result should suffice and this would also remove the demand for a common interface. I'd be all for "no complexity beyond necessary" ...
class RecognitionResult {
private String message = "default message";
private boolean recognized = false;
public Result() {}
public Result(boolean value) {
this.setRecognised(value);
}
public boolean setRecognised(boolean value) {
this.recognized = value;
}
public boolean setMessage(#NonNull String value) {
this.message = value;
}
public boolean getRecognised() {
return this.recognized;
}
#Nullable
public String getMessage() {
return this.recognized ? this.message : null;
}
}
then one can simply do:
return new RecognitionResult(true);
an interface for asynchronous callbacks might look alike this:
interface Recognition {
void OnComplete(RecognitionResult result);
}
or if you really want to optimize:
interface Recognition {
void OnSuccess(RecognitionResult result);
void OnFailure(RecognitionException e);
}
Of course there's no 'correct' design here - it's going to be a matter of opinion which way you go. However my view is that the modern trend in OOD is to minimise the use of extension and to use delegation and implementation of interfaces wherever possible.
As a general rule, whenever you think of using instanceof, reconsider your design.
This would be my suggestion:
interface Result {
boolean isRecognised();
String getMessage();
}
class RecognisedResult implements Result {
private final String message;
public boolean isRecognised() {
return true;
}
public String getMessage() {
return message;
}
}
class UnrecognisedResult implements Result {
public boolean isRecognised() {
return false;
}
public String getMessage() {
throw new UnsupportedOperationException("No message for unrecognised results");
}
}
you can look at the way Retrofit implement your concept of "recognised" and "message"
https://square.github.io/retrofit/2.x/retrofit/retrofit2/Response.html. it is similar to your first method.
what they did is to have a class called Response, containing a method called isSuccessful(), and a method called body() containing the payload if it's successful (or null if it is unsuccessful.
you can try some thing like the following
class Result {
private Type type;
private String message;
public bool isSuccessful(){
return type == RECOGNIZED;
}
public String getMessage(){
return message; //null if unrecognized.
}
enum Type {
RECOGNIZED, UNRECOGNIZED
}
}
The functional way to do this would be to use an Either type, which doesn’t come with the JDK, but is available in vavr library. Based on your comments on this thread, it appears you don’t clearly understand how type inheritance works. In that case, a functional solution may be overkill, and I’d suggest going with #sprinter’s solution.
This is a general issue/problem that I have come across. I wondered if anyone knows of any well suited design patterns or techniques.
private ExternalObject personObject;
private String name;
private int age;
private String address;
private String postCode;
public MyBuilderClass(ExternalObject obj)
this.personObject=obj;
build();
}
public build() {
setName(personObject.getName());
setAge(personObject.getAge());
setAddress(personObject.getAddress());
setPostCode(personObject.getPostCode());
.
.
. many more setters
}
The class above takes external objects from a queue and constructs MyBuilderClass objects.
A MyBuilderClass object is successfully built if all of the fields have been set to non-null non-empty values.
There will be many MyBuilderClass objects that cannot be built because data will be missing from the ExternalObject.
My problem, what is the best way to detect if an object has been correctly built?
I could check for null or empty values in the set methods and throw an exception. The problem with this approach is throwing exceptions is expensive and it will clogg the log files up because there will be many instances where an object cannot be built;
What other approaches could I use?
Correct me if I'm wrong: you are trying to find a good way to check if an object is valid, and if it is not, tell the client code about this without using an exception.
You can try a factory method:
private MyBuilderClass(ExternalObject obj)
this.personObject=obj;
build();
}
public static MyBuilderClass initWithExternalObject(ExternalObject obj) {
// check obj's properties...
if (obj.getSomeProperty() == null && ...) {
// invalid external object, so return null
return null;
} else {
// valid
MyBuilderClass builder = new MyBuilderClass(obj);
return builder.build();
}
}
Now you know whether an object is valid without using an exception. You just need to check whether the value returned by initWithExternalObject is null.
I wouldn't throw exceptions in cases that aren't exceptional. And as the only way for a constructor not to produce an object is to throw, you should not delay validation to the constructor.
I'd still recommend the constructor to throw if its results were to be invalid, but there should be a validation before that, so you don't even call the constructor with an invalid ExternalObject.
It's up to you if you want to implement that as a static method boolean MyBuilderClass.validate(ExternalObject) or by using the builder pattern with this validation.
Another approach for such a validation is to use java Annotations:
Make a simple annotaion class, let's say Validate:
#Target({ElementType.FIELD})
#Retention(RetentionPolicy.RUNTIME)
#interface Validate {
boolean required() default true;
}
then annotate the fields you want to be present as #Validate(required=true):
class MyBuilderClass {
private ExternalObject externalObject;
#Validate(required=true)
private String name;
#Validate(required=false) /*since it's a primitive field*/
private int age;
#Validate(required=true)
private String address;
#Validate(required=true)
private String postCode;
MyBuilderClass(ExternalObject externalObject) {
this.externalObject = externalObject;
build();
}
public void build() {
setName(personObject.getName());
setAge(personObject.getAge());
setAddress(personObject.getAddress());
setPostCode(personObject.getPostCode());
}
//.
//.
//. many more setters
}
And then add this method in the MyBuilderClass class, in order to check if your Object is built correctly:
public boolean isCorrectlyBuilt() throws IllegalAccessException {
boolean retVal = true;
for (Field f : getClass().getDeclaredFields()) {
f.setAccessible(true);
boolean isToBeChecked = f.isAnnotationPresent(Validate.class);
if (isToBeChecked) {
Validate validate = f.getAnnotation(Validate.class);
if (validate.required()/*==true*/) {
if (f.get(this) == null) {
retVal = false;
break;
/* return false; */
}
}
}
}
return retVal;
}
Here is an example of use :
public static void main(String[] args) throws Exception {
ExternalObject personObject = new ExternalObject();
personObject.setAge(20);
personObject.setName("Musta");
personObject.setAddress("Home");
personObject.setPostCode("123445678");
MyBuilderClass myBuilderClass = new MyBuilderClass(personObject);
System.out.println(myBuilderClass.isCorrectlyBuilt());
}
Output : true because the object is correctly built.
This will allow you to choose the fields that you want to be in the structure by reflection, without bringing those inherited from a base class.
As this previous answer suggests, here are 2 options either of which should be added after you have tried to set the variables.
use reflection to check whether any of the variables are null. (As mentioned in comments this will check all fields in this object but be careful with fields in any superclasses).
public boolean checkNull() throws IllegalAccessException {
for (Field f : getClass().getDeclaredFields())
if (f.get(this) != null)
return false;
return true;
}
perform a null check on each variable.
boolean isValidObject = !Stream.of(name, age, ...).anyMatch(Objects::isNull);
Previous answer
From what I've come across you could overwrite the equals method of your object and compare it with a valid example object. Its dirty and might only work in some cases.
Your approach is the best I could think of. Write a seperate method or class that has for example a static validate method. You could reuse it anywhere.
Say I have the following class, with a list as a field:
class Group {
private List<Tile> tiles;
public Group(List<Tile> tiles) {
this.tiles = tiles;
}
public Group() {
this(new LinkedList<>());
}
public List<Tile> getTiles() {
return tiles;
}
}
What would be the best way to ensure the list is in a valid state each time elements are added/removed? (Currently the Tile class doesn't contain any setters so I don't need to worry about elements being modified.)
One possible way is to add a boolean field valid, and a method that updates valid, called after each time an element is added/removed:
class Group {
// ...
private boolean valid;
// ...
public void updateValid() {
// Check list is valid...
valid = true; // Updates `valid`
}
}
Example usage:
group.getTiles().add(new Tile());
group.updateValid();
However, with this there is the possibility of the valid field becoming inconsistent with the list (e.g. if one forgets to call updateValid after adding/removing an element).
Edit
I've since realised a simpler way is to just have a method returning a boolean rather than updating a boolean field, but I'm not sure if this is ideal as it's still possible for the list to be in an invalid state.
The safest solution is to expose individual methods controlling access to the list, instead exposing the entire object:
class Group {
private List<Tile> tiles;
public Group(List<Tile> tiles) {
// defensive copy
this.tiles = new LinkedList<>(tiles);
}
public Group() {
this.tiles = new LinkedList<>();
}
public boolean add(Tile tile) {
// validate *before* inserting
return validate(tile) && tiles.add(tile);
}
}
If your validation logic involves other elements in the list, you can calculate it after inserting:
public void add(Tile tile) {
tiles.add(tile);
updateValid(); // or throw IllegalStateException
}
Another approach would be to use lazy validation instead of expecting the client to call an extra method:
public boolean isValid() {
boolean valid = ... // validation logic here
return valid;
}
Depending on your read/write ratio, this could be more or less expensive than the eager validation you're proposing.
The updateValid() method is a good idea to validate the adding/removing operation.
To force the constraint, this method should not be called by client of the class as in your usage example but by the internal of the class, that is : any method of Group that modifies the List should call the private updateValid() method.
Besides, which is the usefulness of the boolean valid field?
If a validation fails, should you not stop the processing and throw an exception ?
Otherwise, it means that the current state of the Group object could be inconsistent. Which seems undesirable.
You could do it for example :
private void updateValid() {
if (...){ // is not valid
throw new IllegalArgumentException("modification not valid");
}
}
At last, as shmosel said, you should also avoid to provide a public method that get the real list. You could do a defensive copy to avoid change by the clients :
public List<Tile> getTiles() {
return new LinkedList(tiles);
}
I want to create a Wrapper where the wrapped object may be null. If I go to Eclipses Source->generate Delegate Methods option I can choose a member and I'm able to select all methods. The Problem is in generating itself, because I become something like this:
class A {
public boolean aMethod(){
//some stuff
return true //may also return false
}
}
class Awrapper {
private A myA;
public boolean aMethod(){
return myA.aMethod();
}
}
but I need something like this:
class Awrapper {
private A myA;
public boolean aMethod(){
if (myA != null) {
myA.aMethod();
} else {
return false; // or the default for return type like 0 or null
}
}
}
There is an link stating:
"The format of the Delegate Method may be configured on the code Templates page, but all I can find is the generation of comments for delegates. Is this possible? What is taken from the code section to generate the delegate method, not the comment?
I would like to include reformatting the field content in wicket field validation.
Example time input field:
User input: 1459 -> Validation is ok -> field displays reformatted value: 14:59 (with colon in the middle)
Thanks for any help,
uli
public class PhoneValidatorWrapper implements IValidator<String>, Serializable
{
public PhoneValidatorWrapper()
{
}
#Override
public void validate(IValidatable<String> validatable)
{
// validation goes here ...
// writing pretty print back to model
validatable.getModel().setObject("hello world");
}
}
but still value displayed remains unchanged
I would suggest to use javascript that reformats the user input on the client side. The following jQuery plugin could probably do the job:
http://digitalbush.com/projects/masked-input-plugin/#demo
Also see:
How to have users enter a formatted date in wicket?
I finally found out how to do it:
it works by combining validator and behavior:
public class PhoneValidatorWrapper extends Behavior implements IValidator<String>, Serializable
{
String prettyFormattedValue = null;
public PhoneValidatorWrapper()
{
}
#Override
public void validate(IValidatable<String> validatable)
{
// validation goes here ...
prettyFormattedValue = internalValidationResult.getPrettyValue();
}
#Override
public void beforeRender(Component component)
{
super.beforeRender(component);
IModel defaultModel = component.getDefaultModel();
defaultModel.setObject(prettyFormattedValue);
}
}