JAXB annotations on a Quarkus Panache entity causes REST call to fail - java

I have annotated a class to be a Panache Entity. However, I have also included JAXB annotations:
#Entity
#XmlRootElement(name = "Person")
#XmlAccessorType(XmlAccessType.NONE)
public class Person extends PanacheEntity {
#XmlAttribute(name = "Name")
public String name;
}
When I try to return the object from a REST call I get the following exception:
2019-12-08 08:30:01,917 ERROR [org.jbo.res.res.i18n] (vert.x-worker-thread-3) RESTEASY002005: Failed executing GET /person: org.jboss.resteasy.plugins.providers.jaxb.JAXBMarshalException: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
model.Person#name has mutually exclusive annotations #javax.xml.bind.annotation.XmlTransient and #javax.xml.bind.annotation.XmlAttribute
this problem is related to the following location:
at #javax.xml.bind.annotation.XmlTransient()
at model.Person
this problem is related to the following location:
at #javax.xml.bind.annotation.XmlAttribute(namespace="##default", name="Name", required=false)
at model.Person
at org.jboss.resteasy.plugins.providers.jaxb.AbstractJAXBProvider.getMarshaller(AbstractJAXBProvider.java:187)
at org.jboss.resteasy.plugins.providers.jaxb.AbstractJAXBProvider.writeTo(AbstractJAXBProvider.java:149)
So it seems the the Quarkus Panache framework is adding #XmlTransient to my public property.
I can get round this by changing the access of the name property to private and including getters/setters. However, this approach loses one of the benefits of Panache that your code is more compact and readible.
Is there anyway of keeping the public accessor of the class property and still making it work with JAXB?

Interesting use case.
I think we need to check that the attributes don't have any conflicting JAXB annotation before adding the #XmlTransient one automatically.
And it's probably also an issue with JSON-B/Jackson as we do the same thing.
I don't see any obvious workaround: we need to fix it in Quarkus.
Could you open a GitHub issue with a simple reproducer? Thanks!

Related

new keyword with POJO returns null reference to nested objects

I have a POJO with lombok #Data annotation like this
#Data
public class RmsSearchRequestDto {
private AuditCredentialsDto auditCredentialsDto;
private RmsSearchCriteriaDto rmsSearchCriteriaDto;
}
the inner class are POJOs with #Data annotation again.
Now when I create a new instance of RmsSearchRequestDto as:
RmsSearchRequestDto rmsSearch=new RmsSearchRequestDto();
it sets auditCredetialsDto and rmsSearchCriteriaDto to null and results in NullPointerException when I try to access
rmsSearch.getRmsSearchCriteriaDto().getSearchType();
cause rmsSearch.getRmsSearchCriteriaDto() returns null instead of returning an instance of RmsSearchCriteriaDto (desired result)
This behavior is very strange to me and cannot find anything on google. I'm using Spring boot 2.5.6. This is a 20 year old legacy project and I did not have this issue until lately when I tried switch from CustomValidators to Spring Bean Validation. Thanks.
Lombok site is down today but according to what I've heard from others. This is the default behavior of #data annotation as seen in the comments above as well. I changed this class from having only string fields to having nested classes which caused this confusion on my part. Refactoring my test cases to initialize inner class instances explicitly now. Thanks everyone.

Configuring JaVers ID for third party objects

I'm trying to use JaVers to store objects from a 3rd-party library that I can't change. The object definition looks something like:
interface TheirObject extends WithId{
//Other properties here...
}
interface WithId{
String getId();
}
with various implementations of that interface. The ID field is not annotated in anyway.
I tried using the default JaVers configuration and got the following error:
JaversException MANAGED_CLASS_MAPPING_ERROR: given javaClass 'interface TheirObject' is mapped to ValueObjectType, expected EntityType
So I configured JaVers as follows:
javers = JaversBuilder.javers()
.registerEntity(new EntityDefinition(TheirObject.class))
.build();
Which gives the exception:
JaversException ENTITY_WITHOUT_ID: Class 'TheirObject' mapped as Entity has no Id property. Use #Id annotation to mark unique and not-null Entity identifier
So I tried telling it about the id field:
javers = JaversBuilder.javers()
.withMappingStyle(MappingStyle.BEAN)
.registerEntity(new EntityDefinition(TheirObject.class, "id"))
.build();
Which gives the exception:
JaversException PROPERTY_NOT_FOUND: Property 'id' not found in class 'TheirObject'. If the name is correct - check annotations. Properties with #DiffIgnore or #Transient are not visible for JaVers.
I've tried a few different variations of id (e.g. Id, getId) but nothing seems to work and I haven't found the documentation very useful in working out how to proceed.
Could someone please help me configure JaVers properly so I can use it to track changes to these objects? Thanks.
Update: I've changed the interface above to better reflect the issue, as I'd over-simplified it to a point where my examples did actually work.
JaversBuilder.javers()
.registerEntity(new EntityDefinition(TheirObject.class, "id"))
.build();

#Transient not working in hibernate

I am using hibernate 4.1.9.
My code is
#Transient
private String ldapIdTemp;
package is
import javax.persistence.Transient;
Still in hibernate query, it is not working and putting the attribute in the query.
part of query snippet (assetasset0_.ldapIdTemp as ldapIdTemp16_0_, )
I am not sure what I am doing wrong.
Can you try creating setter and getter for the field and annotate the get method with #Transient, as follows:
private String ldapIdTemp;
#Transient
public String getLdapIdTemp() {
return ldapIdTemp;
}
public void setLdapIdTemp(String ldapIdTemp) {
this.ldapIdTemp = ldapIdTemp;
}
Much depends on how you "integrated" this field in your Entity or class hierarchy. Moreover, field vs. property-access could cause an issue for your setting. See this post for a detailed explanation.
In your case, I could imagine that you either:
mixed field and property-access in your entity inheritance strategy
use XML-based configuration for Hibernate in your application.
In both cases the JPA 2.0/2.1 specification clearly states in Section 2.3.1:
It is an error if a default access type cannot be determined and an access type is not explicitly specified
by means of annotations or the XML descriptor. The behavior of applications that mix the placement of
annotations on fields and properties within an entity hierarchy without explicitly specifying the
Access annotation is undefined.
Please check that your persistent Entity classes have either field OR property-based annotations.
Check the #Transient annotation fully qualified name.
It can be from either,
org.springframework.data.annotation.Transient or javax.persistence.Transient.
Try to use javax.persistence.Transient.

'Many To One' attribute type should not be 'Persistence Entity'

I'm trying out IntelliJ IDEA and it's warning me of a Hibernate association that I don't quite understand.
One Side:
#Entity
#Table(name = "MY_REQ_ASSIGNEE")
public class MyRequestAssignee extends BaseUser {
//...
#OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL}, mappedBy = "myRequestAssignee")
private Collection<MyRequest> myRequests = new ArrayList<>();
//...
}
Many Side:
#Entity
#Table(name = "MY_REQUEST")
public class MyRequest implements Persistable {
//...
#ManyToOne(fetch=FetchType.EAGER)
#JoinColumn(name="ASSIGNEE_ID")
private MyRequestAssignee myRequestAssignee;
//...
}
(Persistable is just an interface that has the id property to make sure Hibernate has access to it.)
I see the MyRequestAssignee type underlined in red and the message reads 'Many To One' attribute type should not be 'Persistence Entity'. Are there something wrong with my relationships?
For a sanity check, I looked at this post and this post too.
I found this to be caused by the child entity not being defined in hibernate.cfg.xml. The error message could be improved.
I'm getting this issue in my multi-module Gradle project with Quarkus in IntelliJ,
where I have a OneToOne reference from an entity of module A to an entity of module B.
The code works, so I guess it could be a false flag of IntelliJ
This question is a bit old, but I just wanted to add that this can also be caused by a conflicting hibernate .hbm mapping file and JPA annotations. I ran into this error message when converting old mapping files to annotations and forgot to comment out one of the old mapping files.

Validation Not Working on Nested Objects in Play Framework 2

I'm using the Constraint annotations for validating my objects in Play! framework 2. It works fine for top level objects, but not nested ones. How do I get my nested object validation annotations to work?
Event: The top level object I am saving.
#Entity
public class Event {
#Required
public String name;
#OneToMany(cascade = CascadeType.ALL)
public List<Option> options;
...
}
Option: The nested object. Its not validating the name property.
#Entity
public class Option {
#Required
public String name;
...
}
Not familiar with Play, but it looks very close to javax.validation, in which you'd need to put #Valid on your options field to tell the validator to descend into that relationship. Play has an #Valid of its own, so I'd give that a shot.
Update: As OP pointed out, the above is Play 1.0. Instead, per the Play 2.0 docs, it uses Spring data binding and JSR-303 under the hood, so how about using the javax.validation #Valid annotation on it? Maybe Play 1.0 had a home-made validation framework and they decided to move to javax.validation in 2.0? That would explain why several validation annotations seem to have disappeared in the 2.0 API.

Categories

Resources