PropertyNotWritableException in JSF 1.2 - setter returning value - el

I got some troubles for attribute binding in JSF 1.2 with EL 1.0
public class Bean {
private String name;
public String getName() {
return name;
}
public Bean setName(String name)
this.name = name;
return this;
}
XHTML that give me "Property 'name' not writable" error on form submit:
..
<h:inputText value="#{bean.name}" />
..
Why? It is a 3rd party lib, there is any workaround to solve that case?

Change signature of setName method like this
public void setName(String name)
this.name = name;
}
If you want second constructor in your Bean class, then it should be designed like this
public Bean (String name)
this.name = name;
}

I found a workaround for that case, but clearly it's not the most elegant way to do:
Create a "pseudo extension" of Bean class:
public class BeanExtension {
private Bean instance = new Bean();
public String getName() {
return instance.getName();
}
public void setName(String name)
instance.setName(name);
}
// omitted instance getter and setter methods
}
Since I wanted to override setName method return to "void", now I must use bean.instance to access it attributes, and bean.name to bind name on JSF with EL.

Related

How to receive a JSON File with multiple nodes through a POST Request with JAX-RS and Jackson (Quarkus)

When im tryin got do a Post request through my JAX-RS API it always sends a null value. I dont know if the Jackson annotations are incorrect or if i need to use an ObjectMapper.
These are my classes:
public class ClassA{
private String name;
private ClassB classB;
public ClassA(){}
public ClassA(String name, ClassB classB){
this.name = name;
this.classB = classB;
}
#JsonGetter
public String getName(){ return name; }
#JsonGetter
public ClassB getClassB(){ return classB; }
and this is the classB
public class ClassB{
#JsonProperty("type")
private String type;
#JsonProperty("number")
private int number;
public ClassB(){}
#JsonPropertyOrder({"type, number"})
public ClassB(String type, int number){
this.type= type;
this.number= number;
}
#JsonGetter
public String getType(){ return type; }
#JsonGetter
public int getNumber(){ return number; }
My JSON file:
{
"type": "typeExample;
"classB": {
"type": "classBTypeExample";
"int": 10;
}
}
I want Jackson to read the file and then add an Object type ClassA to a list (the problem is that is not even reading it)
This is the API code:
#Path("/path")
public class Requests {
private Set<ClassA> classesA = Collections.newSetFromMap(Collections.synchronizedMap(new LinkedHashMap<>()));
#GET
public Set<ClassA> list() {
return classesA;
}
#POST
public Set<ClassA> add(ClassA classA){
classesA.add(classA);
return classesA;
}
}
I already added the quarkus.jackson.fail-on-unknown-properties=true to the application.properies file
It was a simple thing that i didnt notice. I forgot to set the values on the constructer. So i just had to add the #ConstructorProperties({}) to the classes constructors and it worked out.

Why do I need to include #JsonProperty with my RestController

Rest Controller:
#RequestMapping(value = "/admin/rest/new-subscriptions")
public List<NewSubscriptionDTO> getNewSubscriptions() {
NewSubscriptionDTO dto = new NewSubscriptionDTO();
dto.setId("54");
dto.setName("John Doe");
return Arrays.asList(dto);
}
NewSubscriptionDTO:
package dermatica.web.admin.rx;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.joda.time.DateTime;
import java.io.Serializable;
public class NewSubscriptionDTO implements Serializable {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I get the following exception:
no properties discovered to create BeanSerializer (to avoid exception,
disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
If I annotate the fields with #JsonProperty it work fine.
Is there a way for the serialization to work automatically without needing this annotation?
#JsonProperty auto-generates a getter/setter that Jackson uses to read/write to the fields during serialization/deserialization. Here are some alternative approaches:
Provide your own public getters/setters for all fields
Make the fields public, generally frowned upon, but if you're creating a simple DTO, that may be acceptable.
Setting ObjectMapper Visibility for FIELD to ANY (see here)
Disable the FAIL_ON_EMPTY_BEANS exception (see here)
Given that your DTO class has getters and setters, this should work without #JsonProperty. I wasn't able to reproduce the exact error message you showed, but here are some suggestions that may help:
[Controller] Explicitly specify the method type as GET, either using method = GET or #GetMapping - not necessary, but it's good to be explicit
[Controller] Make sure you annotate the controller class with #RestController, indicating the response is serialized to JSON and wrapped in an HttpResponse object.
[DTO] You don't need to extend Serializable (see here).
The final controller would look like this:
#RestController
public class MyController {
#GetMapping(value = "/admin/rest/new-subscriptions")
public List<MyDTO> getDTO() {
MyDTO dto = new MyDTO();
dto.setId("54");
dto.setName("John Doe");
return Collections.singletonList(dto);
}
}
Response:
[{"id":"54","name":"John Doe"}]

Can I refer to properties directly in entity constructor with EclipseLink?

EclipseLink version is 2.5.1
We've moved from GlassFish web-server to TomCat. This made us switch to static weaving because with TomCat dynamic weaving doesn't really work that easy.
Now that static weaving works, it seems to work quite a bit differently.
If I have an entity which sets some property directly in the constructor:
class Entity {
#Column
private String name;
public Entity() {
name = "something";
}
public String getName() {
return name;
}
}
Long story short this test will fail:
Entity e = new Entity();
assertEquals("something", e.getName()); // e.getName() returns null
This happens because getName(), after weaving, is not returning this.name anymore. Instead it calls a routing for initialization (if it's needed) and (I guess) gets the value of the property from some underlying HashMap.
But constructor is not being weaved, I even have looked into the sources of weaver and seems to be explicitly opting out of this:
/**
* Construct a MethodWeaver and allow it to process the method.
*/
#Override
public MethodVisitor visitMethod(int access, String methodName, String desc, String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, methodName, desc, signature, exceptions);
if (!alreadyWeaved) {
// skip constructors, they will not changed
if (!"<init>".equals(methodName) && !"<cinit>".equals(methodName)) {
// remaining modifications to the 'body' of the class are
// delegated to MethodWeaver
mv = new MethodWeaver(this, methodName, desc, mv);
}
}
return mv;
}
The question is, maybe I miss something here? Is it the actual reality with EclipseLink 2.5.1 that you can't use properties directly in entity's own ctor? (and it's not even mentioned anywhere, not googlable at least)
It turns out yes, we can.
But there was a problem that led us to the property being not visible to the getter.
We actually have MappedSuperclass inheritance here and we were shadowing this field in the child class. Essentially this:
class A {
#Column()
protected String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
class B extends A {
#Column()
protected String name;
// no #Override here
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
So we were just shadowing the property.

Jackson deserialization issue with access modifier

Jackson throwing an exception in deserialization with protected access modifier.
I am trying to deserialize one object then accessing protected properties of parent class is throwing exception.
Class com.fasterxml.jackson.databind.deser.impl.FieldProperty can not
access a member "protected"
Make sure that Jackson can see protected fields. E.g.
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PROTECTED_AND_PUBLIC;
#JsonAutoDetect(fieldVisibility = PROTECTED_AND_PUBLIC)
class Person {
protected String name;
}
Or define getters and setters as needed. E.g. :
class Person {
protected String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

Behaviours of new constructor added by AspectJ ITD

I am currently applying AspectJ to our project, and I found a behavior which is a bit strange to me.
Q1:
I added a new constructor to my current class with inter-type declaration, and found that the class's member variable is not initialized if the new constructor is used to instantiate my class.
For example:
The class which I'll add a new constructor to:
public class Child {
public String name = "John";
public Child(String desc) {
// TODO Auto-generated constructor stub
}
}
The aspectJ code:
public aspect MyTest {
public Child.new(String desc, int num) {
System.out.println("Child Name:" + this.name);
}
}
If I instantiate the Child with the new constructor:
new Child("A child", 5)
the member variable this.name is not initialized as will be done with the original constructor.
But, if I call the original constructor:
new Child("A child")
the member variable this.name will be initialized to "John" as usual
The result:
Child Name:null
Is this a limitation of AspectJ? Is there anyway to resolve this issue?
I don't really want to add the code for member variable initialization to the new constructor.
Q2:
It seems in the newly added constructor, super.method() can not be correctly resolved.
The class which I'll add a new constructor to:
public class Child extends Parent{
public String name = "John";
public Child(String desc) {
}
}
Child extends Parent. Parent has a method init()
public class Parent {
public void init() {
//....
}
}
I add a new constructor for the Child in my aspect.
public aspect MyTest {
public Child.new(String desc, int num) {
super.init();
}
}
The above aspect code will trigger an exception.
Exception in thread "main" java.lang.NoSuchMethodError: com.test2.Child.ajc$superDispatch$com_test2_Child$init()V
at MyTest.ajc$postInterConstructor$MyTest$com_test2_Child(MyTest.aj:19)
at com.test2.Child.<init>(Child.java:1)
at MainProgram.main(MainProgram.java:11)
My workaround is to define another method for my class Child, and indirectly call the super.method() within that method
For example, add a new method that calls super.init() for Child
public void Child.initState()
{
super.init();
}
Now, I can call initState() in the newly added constructor like below:
public aspect MyTest {
public Child.new(String desc, int num) {
this.initState();
}
}
Is this a limitation of AspectJ? Is this the only way to resolve this issue?
Thank you all for your time :)
Foe the first questions, it seems that the lint warning will appear when compiling:
(unless you close the lint warning)
"inter-type constructor does not contain explicit constructor call: field initializers in the target type will not be executed [Xlint:noExplicitConstructorCall]"
Therefore I'd say it's an AspectJ's limitation.
The best way to do this might be call the other constructors of Child in the constructor added by AspectJ
For example:
public aspect MyTest {
public Child.new(String desc, int num) {
this("Hello"); // -> This will call the constructor of Child, and trigger fields initialization
System.out.println("Child Name:" + this.name);
}
}
For the second question, I think it's a bug of aspectJ.
That decompile the woven target byte code will find that the method “com.test2.Child.ajc$superDispatch$com_test2_Child$init()V” will be inserted. It implies this method should be generate by aspectJ, but there is no such method in the byte code.
The code for an ITD introduction is no different that the code that you would add to a class directly. So without member initialization code in your introduced constructor, members will , of course, remain uninitialized. So you need to change you code in Q1 as follows.
public Child.new(String name, int age) {
this.name = name;
this.age = age;
System.out.println("Child Name:" + this.name);
}
As for Q2, it works fine for me.
class Parent {
public void init() {
System.out.println("P.init");
}
}
class Child extends Parent {
}
aspect Intro {
public void Child.init(){
super.init();
System.out.println("C.init");
}
}
public class Main {
public static void main(String[] args) {
Child c = new Child();
c.init();
}
}
prints:
P.init
C.init
Changing the introduced method to something other than init works too (to match your code).
Regarding your comment: I fail to see what difference you have made in Q1. Sorry, I don't get it.
As for Q2 part of your comment, constructor arrangement works for me:
class Parent {
protected String name;
public Parent(String name) {
this.name = name;
}
}
class Child extends Parent {
int age;
public Child(String name) {
super(name);
}
}
aspect Intro {
public Child.new(String name, int age){
super(name);
this.age = age;
System.out.println("this.name: " + this.name + " this.age: " + this.age);
}
}
prints this.name: myname this.age: 2