I'm using javax.validation to validate some bean fields' values.
This is what I use normally:
public class Market {
#NotNull
#Size(max=4)
private String marketCode;
#Digits(integer=4, fraction=0)
private Integer stalls;
// getters/setters
}
This will make sure that every Market instance has a market code with a maximum length of 4 characters and a number of stall with a maximum of 4 integer digits and 0 decimal digits.
Now, I use this bean to load/store data from/to DB.
In the DB I have table Markets defined like this:
CREATE TABLE MARKETS (
MARKET_CODE VARCHAR2(4 BYTE) NOT NULL,
STALLS NUMBER(4,0)
)
As you can see, I have MARKET_CODE which can be at most 4 bytes long. The #Size annotation will check if the string is at most 4 characters long, which is wrong.
So, the question is: is there an annotation like #Size that will check for the string bytes instead of the characters?
Check the Hibernate Validator documentation on Creating custom constraints.
Your validator will need to encode the String into a byte[], using some default or specified Charset. I imagine you might well use UTF-8.
Maybe something like this, which uses a hard coded UTF-8 encoding and assumes a suitable annotation, as outlined in the Hibernate documentation linked.
public class MaxByteLengthValidator implements ConstraintValidator<MaxByteLength, String> {
private int max;
public void initialize(MaxByteLength constraintAnnotation) {
this.max = constraintAnnotation.value();
}
public boolean isValid(String object, ConstraintValidatorContext constraintContext) {
return object == null || object.getBytes(Charsets.UTF_8).length <= this.max;
}
}
Related
I'm using Jackson JSON parser. I have simple data transfer object which should be returned via REST service.
public class PersonDto {
private String name;
private Integer age; // int?
public PersonDto(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public Integer getAge() {
return this.age;
}
}
Should I favor wrapper classes over primitive types as fields in such case? Which of these approaches has more advantages, except that wrapper is nullable?
Wrapper class: java.lang.Integer
Pros:
Allows null value, therefore giving the chance to the user to leave a blank / non-specified field
Fast when values are between -128 and 127, as it uses its internal cache instead of creating new objects
Integer::valueOf for parsing String's
Cons:
Immutable: if you have to reset the value (e.g: because it exceeded a certain range), you'll have to re-create a whole new Integer instance.
Slower calculation performance
java.lang.Integer is a reference to an instance. Each calculation will recreate a whole new Object
Primitive type: int
Pros:
Mutable (as long as non-final, and a setter is provided): easily allows: this.age = age > MAX_AGE ? blabla : age;
primitive types calculations are faster
Integer::parseInt for parsing String's
Cons:
Non-selected values will be automatically set to 0; this may create confusion on whether the user selected 0 as value, or did not select anything
It seems the only advantage of java.lang.Integer is the blank / null value.
Also, in cases where a wrapper is needed, e.g:
List<Integer> myList;
you can directly add an unboxed value myList.add(2); which is interpreted by the compiler as myList.add(Integer.valueOf(2));
I found using wrapper in DTO's beneficial. With Jackson, for nullable fields you can set #JsonInclude(JsonInclude.Include.NON_NULL) on top of the DTO object and reduce the number of data sent via network (null fields will not be present in resulting JSON), thus resolving ambiguity if value is 0 or not present, telling the front-end that no node is present and hence no processing/displaying data is needed.
For non-nullable numeric data, primitive works well.
Also, for floating-point data that are not supposed to be used in front-end in arithmetic calculations, one can use String with rounding performed on server-side. I saw this technique multiple times in REST API's.
DecimalFormat df = new DecimalFormat("#.####");
df.setRoundingMode(RoundingMode.CEILING);
System.out.println(df.format(d));
I know that HashCode is a way, but I've noticed that after a while the HashCode change. So, I have an application that permit to buy things, every article is identified by a code generated by now from the hashcode and stored in the db PostgreSQL, but I have discovered this issue so I can't use it. Infact the next day that I try to identify this article on the db the hashcode changed so it doesn't works. What is a solution? Thanks a lot!
My object that generate code for article is something like this
public class AcquistoDVDRichiesto implements IsSerializable, CustomEnum {
private int codice_carrello;
private String utente;
private int numero;
private String film;
private int fornitura;
public AcquistoDVDRichiesto(){}
public AcquistoDVDRichiesto(int c, String user){
utente=user;
codice_carrello=c;
}
public void generateCodeBasket(){
if(film!=null && numero!=0 && fornitura!=0){
codice_carrello=Math.abs(film.hashCode()+((Integer)numero).hashCode()+
((Integer)fornitura).hashCode()+tipo_supporto.DVD.hashCode());
}
}
}
-
You shouldn't generate db primary keys by hand. The best approach is to let the database generate the unique primary keys for each record. This way you can be sure that there will be no primary key collisions and the codes will not change.
In PostreSQL, you can use a SERIAL column type to achieve that. Example:
CREATE TABLE tablename (
colname SERIAL
);
The other way is to use a sequence, but it is a bit more complicated.
I have the following variable annotated for data validation:
#Size(min=8, max=16, message="the size of the parameter must be between 8 and 16")
private String param;
However, the param can be null. It is required that it be 8-16 chars long only if it is not null. The problem I face is if the client app (JSON API) supplies an empty string, I want to treat it as though it were not supplied at all, i.e. is null. I was wondering if there is an elegant way to do this using the javax.validation annotations, i.e. convert an empty string to null, as opposed to the plain Java way the way I'm doing it right now:
public void setParameter(String _param) {
if(_param != null && !_param.trim().isEmpty()){
this.param = _param;
} else {
this.param = null;
}
}
I would like to have a very simple setter:
public void setParameter(String _param) {
this.param = _param;
}
and have the is-empty-string boilerplate done by an annotation. Is there a way to do it?
You could can implement your own custom constraint validator.
see here. I've used this many times and works like a charm.
https://docs.jboss.org/hibernate/validator/5.0/reference/en-US/html/validator-customconstraints.html
You would just need to set this condition (if null return "" or vice-versa) in the isValid method.
An example is as follows:
SEG1|asdasd|20111212|asdsad
SEG2|asdasd|asdasd
SEG3|sdfsdf|sdfsdf|sdfsdf|sdfsfsdf
SEG4|sdfsfs|
Basically, each SEG* line needs to be parsed into a corresponding object, defining what each of those fields are. Some, such as the third field in SEG1 will be parsed as a Date.
Each object will generally stay the same but there may be instances in which an additional field may be added, like so:
SEG1|asdasd|20111212|asdsad|12334455
At the moment, I'm thinking of using the following type of algorithm:
List<String> segments = Arrays.asList(string.split("\r"); // Will always be a CR.
List<String> fields;
String fieldName;
for (String segment : segments) {
fields = Arrays.asList(segment.split("\\|");
fieldName = fields.get(0);
SEG1 seg1;
if (fieldName.compareTo("SEG1") == 0) {
seg1 = new Seg1();
seg1.setField1(fields.get(1));
seg1.setField2(fields.get(2));
seg1.setField3(fields.get(3));
} else if (fieldName.compareTo("SEG2") == 0) {
...
} else if (fieldName.compareTo("SEG3") == 0) {
...
} else {
// Erroneous/failure case.
}
}
Some fields may be optional as well, depending on the object being populated. My concern is if I add a new field to a class, any checks that use the expect field count number will also need to be updated. How could I go about parsing the rows, while allowing for new or modified field types in the class objects to populate?
If you can define a common interface for all to be parsed classes I would suggest the following:
interface Segment {}
class SEG1 implements Segment
{
void setField1(final String field){};
void setField2(final String field){};
void setField3(final String field){};
}
enum Parser {
SEGMENT1("SEG1") {
#Override
protected Segment parse(final String[] fields)
{
final SEG1 segment = new SEG1();
segment.setField1(fields[0]);
segment.setField1(fields[1]);
segment.setField1(fields[2]);
return segment;
}
},
...
;
private final String name;
private Parser(final String name)
{
this.name = name;
}
protected abstract Segment parse(String[] fields);
public static Segment parse(final String segment)
{
final int firstSeparator = segment.indexOf('|');
final String name = segment.substring(0, firstSeparator);
final String[] fields = segment.substring(firstSeparator + 1).split("\\|");
for (final Parser parser : values())
if (parser.name.equals(name))
return parser.parse(fields);
return null;
}
}
For each type of segment add an element to the enum and handle the different kinds of fields in the parse(String[])method.
You can use collections, e.g. ArrayList
You can use var-args
If you want to make it extensible, you may want to process each segment in a loop, instead of handling each occurance.
I would add a header row to your file format with the names of the fields being stored in the file so it looks something more like this:
(1) field1|field2|field3|field4|field5
(2) SEG1|asdasd|20111212|asdsad|
(3) SEG2|asdasd||asdasd|
(4) SEG3|sdfsdf|sdfsdf|sdfsdf|sdfsfsdf
(5) SEG4|sdfsfs|||
This is common for CSV files. I've also added more delimiters so that each line has five 'values'. This way a null value can be specified by just entering two delimiters in a row (see the third row above for an example where a null value is not the last value).
Now your parsing code knows what fields need to be set and you can call the setters using reflection in a loop. Pseudo code:
get the field names from the first line in the file
for (every line in the file except the first one) {
for (every value in the line) {
if (the value is not empty) {
use reflection to get the setter for the field and invoke it with the
value
}
}
}
This allows you to extend the file with additional fields without having to change the code. It also means you can have meaningful field names. The reflection may get a bit complicated with different types e.g. int, String, boolean etc. so I would have to say that if you can, follow #sethu's advice and use a ready-built proven library that does this for you.
Is there a necessity to use the same string with | as a delimiter? If the same classes are used to create the String, then its an ideal case for Xstream. Xstream will convert your java object into XML and back. Xstream will take care of the scenario where some fields are optional. You will not have write any code that parses your text. Here's a link:
http://x-stream.github.io/
I have an entity with Integer attributes that looks like this in proto code:
class MyEntity:
String name
#Choices({1, "BSD", 2, "Apache", 3, "GPL"}
Integer frequency
#ChoicesSegment({1000, 2000, 3000}, {"BSD", "Apache", "GPL"})
Integer type
String getFrequency()
return getChoice("frequency", frequency)
String getType()
return getChoice("type", type)
maybe this solution is more feasible:
class MyEntity:
String name
final static private Something? frequencyChoices = {1000, 2000, 3000}, {"BSD", "Apache", "GPL"}
Integer frequency
final static private String[] typeChoices = new String[] {"BSD", "Apache", "GPL"}
Integer type
#Choices(MyEntity.frequencyChoices)
String getFrequency()
return frequency)
#IntervalChoices(MyEntity.typeChoices)
String getType()
return type
*get** accessors return strings according to this table.
value(type) HumanReadableString(type)
1 BSD
2 Apache
3 GPL
min frequency max frequency HumanReadableString(frequency)
0 1000 rare
1000 2000 frequent
2001 3000 sexy
It should be possible to get all possible values that an attribute can take, example:
getChoices(MyEntity, "type") returns ("rare", "frequent", "sexy")
It should be possible to get the bound value from the string:
getValue(MyEntity, "frequency", "sexy") returns (2000,3000)
edit: purpose of all of this This methods should simplify the generation of forms and requests (of course this should not be view implementation bound)
edit: added how I would like to tell Java that some attributes are spécial so that it can generate get* accessors acordingly.
edit: added how to submit in the code the choices
edit: the only thing that I store in the db is integers, when I want to print them they should be converted somehow to their human readable string.
You can have additional info in enums:
public enum License {
GPL("GPL"),
APACHE("Apache License");
public License(String displayName) {
this.displayName=displayName;
}
String displayName;
}
Additional functions as required, but have a close look which functions are already provided by the Enum classes.
You can do it without any hassle (but note, that the value in the DB will be the ordinal() value of the enums. So:
public enum License { GPL, APACHE, BSD }
FrequencyChoices could go into an #ElementCollection.
If you need human readable values, you may want to convert your Enum to an ordinary class, and persist it as a separate table, so you can add new licenses more easily to the list...
#Entity
public class License {
#Id long id;
String name;
}
I have not tried to persist this but you can try following http://marekhalmo.blogspot.sk/2012/09/cool-java-enums.html
I would stick to enums.