Pages

Tuesday, 11 March 2014

SOLVED: JAXBException "The property or field ---- is annotated to be transient so can not be included in the proporder annotation".

Usecase:
Fixing the JAXBException "The property or field ---- is annotated to be transient so can not be included in the proporder annotation". 

Brief:
Recently, I was facing an issue with one of my REST services. On running the service all I could see were empty tags, although my service actually returned a list of employees.

Apart from this, on adding propOrder property, I kept hitting an exception "The property or field count is annotated to be transient so can not be included in the proporder annotation" at runtime, although none of my fields/methods were marked transient!!

After a long drill, the cause of both these problems was boiled down to the fact that I had a getter without a corresponding setter method!!!

Steps:

To demonstrate the problem and the solution thereafter, I have created a sample app EmpAppWithoutSetter.zip.
We will mainly focus on the EmployeeList.java class here.
The whole app is a simple Employee app which has all the CRUD operations, one of them being GET which returns all the employees and the number of employees.

If you run this app, you will find the below exception being logged in the console:

[Exception [EclipseLink-50009] (Eclipse Persistence Services - 2.4.1.v20120725-495bda0): org.eclipse.persistence.exceptions.JAXBException

Exception Description: The property or field count is annotated to be transient so can not be included in the proporder annotation.]

..............


If you look at the code, the field 'count' in EmployeeList.java has not been marked transient explicitly.

Also, just to play around a bit, remove the @XmlType annotation from EmployeeList.java class. Now, if you run the service, no exception occurs.
However, the XML structure will be as shown below:



            
Although there is an employee entry, the data is not shown at all. The reason for this is that in EmployeeList.java, we have getters for the fields 'list' and 'count'. However, we do not have their corresponding setter methods.
The exception thrown in the first case and an emplty list being displayed in the second case are each correct behaviour.
For more details, refer the EclipseLink bug.
Any one of the below three approaches can be used to fix the issue:
Approach 1:
Mark the fields public.
For example, in our case, we would need to declare our fields as below:
    public List<Employee> list = new ArrayList<Employee>();  
    public int count;
However, this is not the best approach, as marking fields public unnecessarily is quite unadvisable.
Approach 2: 
Create a setter method for every getter method that you have.
In our example, we would need to create setter methods corresponding to the getter methods, getList() and getCount(), as below:
    public void setList(List<Employee> list) {
        this.list = list;
    }

    public void setCount(int count) {
        this.count = count;
    }
Approach 3:
Add the annotation @XmlElement on top of the stand alone getter methods.
In this example, add it as shown:
   @XmlElement
    public List<Employee> getList() {
        return list;
    }
   
    @XmlElement
    public int getCount() {
        return count;
        }
The same three approaches hold good if you have setters without correponding getters.
On applying one of the above approaches and running the service, you should be able to get the required output.




No comments:

Post a Comment