I have the following form:
public class Form {
#NotBlank(errorCode = "my.custom.error")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
My goal is to reject value with specified error code.
But unfortunately, I cannot do it.
The field rejected with my message wrapped by Form name.
Will be good to know in which way error code for the similar annotation can be specified?
Related
I repeatedly saw code like the following, where the empty constructor was deleted by well-intentioned developers (because it appeared unused), which then broke Jackson serialization (caught by tests later on):
public class Person {
private String name;
private int age;
// appears unused – only used by Jackson
public Person() {}
// used in code
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
I'm thinking of adding a #JsonCreator annotation to the empty constructor to make it more obvious that the constructor is used by Jackson to prevent developers from removing it:
public class Person {
private String name;
private int age;
#JsonCreator // <--------
public Person() {}
// used in code
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Is this a good idea or does this have unintended consequences (i. e. changing semantics compared to the no-annotation case)?
Or is this use of #JsonCreator an anti-pattern and there is a better way to achieve this (short of converting the class to a record)?
Reading more documentation about this I and regarding all the comments to the question and other answer(s) I came to the conclusion that it really is an anti-pattern to use the #JsonCreator for the default constructor.
The Javadoc (e.g. from version 2.13) specifies that a ctor annotated with that annotation should have at least one parameter. (It doesn't explicitly say so, but a ctor without arguments would be useless more or less.)
NOTE: when annotating creator methods (constructors, factory methods), method must either be:
Single-argument constructor/factory method without JsonProperty annotation for the argument: if so, this is so-called "delegate creator", in which case Jackson first binds JSON into type of the argument, and then calls creator. This is often used in conjunction with JsonValue (used for serialization).
Constructor/factory method where every argument is annotated with either JsonProperty or JacksonInject, to indicate name of property to bind to
So for your problem I would suggest that you get rid of the default ctor and instead annotate at least one of the remaining ctor(s) used in code as well properly. Jackson can use that and the IDE will not mark it as unused.
It also could save you from workarounds for not properly or completely initialized objects.
In your example this could be
public class Person {
private String name;
private int age;
#JsonCreator
public Person(#JsonProperty("name") String name, #JsonProperty("age") int age) {
this.name = name;
this.age = age;
}
// other getters / setters / business logic come here
}
It's an anti pattern, because the default constructor is the #JsonCreator default and everyone knows it - it is useless code.
You don't need to prevent developers from removing it because your functional tests will fail if they do so.
The Java POJO is like this:
import javax.validation.Valid;
import com.fasterxml.jackson.annotation.JsonProperty;
Class MyClass{
#JsonProperty(value = "config-meta-info")
#Valid
private ConfigMetaInformation configMetaInfo;
#JsonProperty(value = "name")
#Valid
private String name;
public MyClass(){}
public MyClass(String name,ConfigMetaInformation configMetaInfo){
this.name=name;
this.configMetaInfo=configMetaInfo;
}
#JsonProperty("name")
public String getName() {
return name;
}
#JsonProperty("name")
public void setName(String name) {
this.name = name;
}
#JsonProperty("config-meta-info")
public ConfigMetaInformation getConfigMetaInfo() {
return configMetaInfo;
}
#JsonProperty("config-meta-info")
public void setConfigMetaInfo(ConfigMetaInformation configMetaInfo) {
this.configMetaInfo= configMetaInfo;
}
}
I am Using the JSON as below:
{
"name":"abc",
"config-meta-info":"someInfo"
}
But when I try to get the Data from the MongoDB document , I am seeing the config-meta-info as null.
Am I missing anything to handle this kebab-case key?
I could be wrong in the case of MongoDB but in other JSON based databases, they don't allow hyphenation in the field/key, underscores are usually preferred. Instead of config-meta-info, try config_meta_info.
The structure which you showed:
{
name:"abc",
config-meta-info:"someInfo"
}
is not a JSON.
Specification RFC-8259 defines all types (6) but what is name or config-meta-info? It can be JavaScript, but not a JSON.
The proper JSON:
{
"name":"abc",
"config-meta-info":"someInfo"
}
And you can use hyphen without limitations.
I've been searching for hours on here and on the Vaadin forums, but I seem to have a unique problem here.
I simplified my problem a lot to be able to illustrate it easily.
So I have a Bean class:
public class Bean {
private String name;
private NestedBean nestedBean;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public NestedBean getNestedBean() {
return nestedBean;
}
public void setNestedBean(NestedBean nestedBean) {
this.nestedBean = nestedBean;
}
Bean() {
this.name = "Bean";
this.nestedBean = new NestedBean();
}
}
And its nested field, class NestedBean:
public class NestedBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
NestedBean() {
this.name = "NestedBean";
}
}
So now I want to bind an instance of Bean to two TextFields, with the help of a BeanFieldGroup:
Bean bean = new Bean();
BeanFieldGroup<Bean> binder = new BeanFieldGroup<>(Bean.class);
binder.setItemDataSource(bean);
addComponent(binder.buildAndBind("Name", "name"));
addComponent(binder.buildAndBind("Nested name", "nestedBean.name"));
This, however, throws this exception:
java.lang.IllegalArgumentException: Property com.reygok.vaadin.main.Bean.nestedBean is not cascaded
Caused by: org.apache.bval.jsr.UnknownPropertyException: Property com.reygok.vaadin.main.Bean.nestedBean is not cascaded
I tried different solutions, like:
Creating the TextFields first and then using
binder.bind(textField, "nestedBean.name");
Doing this first:
binder.getItemDataSource().addNestedProperty("nestedBean.name");
But nothing changed the Exception. So does someone know what causes this?
Thanks a lot in advance!
I found it, so if others have the same problem:
The solution is to add the #Valid annotation to the fields that have nested fields inside of them.
So in my example:
public class Bean {
private String name;
#Valid
private NestedBean nestedBean;
...
I recommand you to bind member before setting bean data source
BeanFieldGroup<Bean> binder = new BeanFieldGroup<>(Bean.class);
// first
addComponent(binder.buildAndBind("Name", "name"));
addComponent(binder.buildAndBind("Nested name", "nestedBean.name"));
// then
binder.setItemDataSource(bean);
I'm trying to parse JSON using Retrofit and Gson, but I need to map one JSONfield
's value to multiple JAVA fields inside bean class.
Here is an example code:
class A{
#SerializedName("name");
private String name;
#SerializedName("name");
private String fullName;
}
This is the error I'm seeing: class A declares multiple JSON fields named name. Is there any way to do this?
Update: Please avoid suggesting removing one field from the bean or making changes into getter and setter. The project is huge, and the field is being used later in many other cases, so I don't want to mess with the structure. The question is pretty much clear and on the point.
No need to declare JSON for fullname use name value with fullname in setter gatter.
class A{
#SerializedName("name");
private String name;
private String fullName;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFullName() {
return name;
}
public void setFullName(String fullName) {
this.name = fullName;
}
}
Is there a way to edit the content behavior or is there a plugin that does the following ... ?
I have a JSF project
the content assistant completes phrases only for attributes that has getters/setters methods
#ManagedBean(name = "myBean")
#ViewScoped
public class ViewScopedBean {
String name;
String age;
public ViewScopedBean() {
}
public String method() {
return null;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
using ctrl+space in <h:commandButton value="action listener" actionListener="#{myBean.<ctrl+space>}" /> shows only methods and name attribute, is there away to make it also show the age attribute ?