Thymeleaf not recognizing Lombok getters and setters - java

Lombok plugin is installed. Using IntelliJ 15. Structure of model shows the getters and setters but I get the following error from Thymeleaf.
Error:
Invalid property 'postTitle' of bean class [com.blog.domain.Post]: Bean property 'postTitle' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
The model:
#Entity
public #Data class Post {
#Id
#GeneratedValue
private Long id;
#NotEmpty
private String postTitle;
#NotNull
#ManyToOne
private Author postAuthor;
#NotNull
#Temporal(TemporalType.DATE)
private Date postDate;
#Column(columnDefinition = "TEXT")
private String postTeaser;
#Column(columnDefinition = "TEXT")
private String postBody;
}
The controller method that loads the form:
#GetMapping("/create")
public String postForm(Post post, Model model) {
model.addAttribute("authors", authorService.getAllAuthors());
return "postform";
}
The field where error occurs:
<input id="postTitle" type="text" th:field="*{postTitle}" />
Any ideas where I'm going wrong? Adding the getters and setters manually solves the problem. What is lombok doing here that is breaking it?

I ran into this using a boolean named "isEnabled". Renaming it to "enabled" worked. Not sure about the reason for this though.

Related

How do I use a JPARepository inside of a PrePersist Annotation?

I have an alert table which is transactional and an alert type table which is master. I would like to send out an email whenever an alert is added to the table, so I figured I would use PrePersist. However, in my email, I want to include some information that is included in the alert type table.
I have tried to add a reference to the AlertTypeRepository in the Alert class but I can't because my alert class is a #Table and alertTypeRepository is not a column.
Below is my Alert class
#Entity
#Table
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class Alert {
#Id
#GeneratedValue
int id;
#Column
String name;
#Column
String alertTypeId;
#Column
String detailedMessage;
#Column
String status;
#Temporal(TemporalType.TIMESTAMP)
Date time;
}
Below is my AlertType class
#Entity
#Table
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class AlertType {
#Id
#GeneratedValue
int id;
#Column
String name;
#Column
String header;
#Column
String footer;
#Column
String summary;
#Column
String deliveryType;
#Column
Boolean active ;
#Column
String recipients;
}
I would like to have a PrePersist function inside of the Alert class. That allows me to access its corresponding header and footer from the AlertType class.
I figured out a solution so I hope this helps anyone facing a similar issue. Basically I had to create an EntityListener to the Alert class and then add the following class.
#Component
public class AlertListener {
static AlertTypeRepository alertTypeRepository;
#Autowired
public void init(AlertTypeRepository alertTypeRepository)
{
this.alertTypeRepository = alertTypeRepository;
}
#PrePersist
public void prePersist(Alert alert) {
List<AlertType> alertType= this.alertTypeRepository.findAll();
}
}
As I know the are two approaches to archive the purpose. Your alterType is not managed by Spring .
Define a JPA EntityListener and apply it on your entity class, which does not seem to interest you.
The second approach, annotated your entity with Spring #Configurable annotation:
#Configurable(preConstruction = true)
class AlterType{
#Inject YourRepository bean as normal.
}
To make it work. Firstly you have to add aspectj related jars into your project dependencies. Secondly you can choose load-time weaving or compile-time weaving to handling the injection for you class.
There is an example of aspectj compiler config in Maven can be used for compile-time weaving(note, just for aspectj compiler maven plugin config, I did not use #Configurable here.).

xHow can I have #Id string for CrudRepository in Spring with Spring Data JPA?

The problem is that I am getting an exception using #RepositoryRestResource for my UserRepository that extends JpaRepository.
The reason for that is that findById is only accepting Long or Int types by default, even I have
#Id String id; and not #Id Int id in my entity definition.
I have tried searching StackOverflow and Google, but haven't found any solutions.
The error message is as follows:
"Failed to convert from type [java.lang.String] to type [java.lang.Integer] for value '3175433272470683'; nested exception is java.lang.NumberFormatException: For input string: \"3175433272470683\""
I want to make it work with a
#Id String id;
Any suggestions?
Many thanks in advances. It's a big privilege to ask questions here.
The Entity class:
#Entity // This tells Hibernate to make a table out of this class
#Table(name = "users")
public class XmppUser {
#Id
private java.lang.String username;
private String password;
private String serverkey;
private String salt;
private int iterationcount;
private Date created_at;
// #Formula("ST_ASTEXT(coordinates)")
// #Column(columnDefinition = "geometry")
// private Point coordinates;
// private Point coordinates;
private String full_name;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "username", nullable = true)
private XmppLast xmppLast;
You must change the type of the ID type parameter in the repository to match with the id attribute type on your entity.
From the Spring docs:
Interface Repository<T,ID>
Type Parameters:
T - the domain type the repository manages
ID - the type of the id of the entity the repository manages
Based on
#Entity // This tells Hibernate to make a table out of this class
#Table(name = "users")
public class XmppUser {
#Id
private java.lang.String username;
//...
}
It should be
public interface UserRepository extends CrudRepository<XmppUser, String> {
//..
}
See:
https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/repository/CrudRepository.html#findById(ID)
https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/repository/Repository.html
You could try something like this:
#Id
#GeneratedValue(generator = "uuid")
#GenericGenerator(name = "uuid", strategy = "uuid2")
#Column(name = "PR_KEY")
private String prKey;
If you want to read more about this subject you could begin looking throw here or here
according to the latest version of spring data jpa(2.1.10 GA), you can use it like
here is the link
JpaRepository is a special case of CrudRepository. Both JpaRepository and CrudRepository declare two type parameters, T and ID. You will need to supply these two class types. For example,
public interface UserRepository extends CrudRepository<XmppUser, java.lang.String> {
//..
}
or
public interface UserRepository extends JpaRepository<XmppUser, java.lang.String> {
//..
}
Notice that the second type java.lang.String must match the type of the primary key attribute. In this case, you cannot specify it as String or Integer, but it is java.lang.String instead.
Try not to name a customized class as String. It is a bad practice to use the same class name as already present in the JDK.
I think there is an approach to solve this problem.
Let's say, Site is our #Entity.
#Id
private String id;
getters setters
then you can invoke findById as follow
Optional<Site> site = getSite(id);
Note: this worked for me, I hope it will help someone.

#JsonIgnore with #Getter Annotation

Can I use #JsonIgnore with #Getter annotation from lombok without explicitly define the getter, because I have to use this JsonIgnore while serializing the object but while deserializing, the JsonIgnore annotation must be ignored so the field in my object must not be null?
#Getter
#Setter
public class User {
private userName;
#JsonIgnore
private password;
}
I know, just by define the JsonIgnore on the getter of password I can prevent my password to be serialized but for that, I have to explicitly define the getter thing that I don't want.
Any idea please, Any help will be appreciated.
To put the #JsonIgnore to the generated getter method, you can use onMethod = #__( #JsonIgnore ). This will generate the getter with the specific annotation. For more details check
http://projectlombok.org/features/GetterSetter.html
#Getter
#Setter
public class User {
private userName;
#Getter(onMethod = #__( #JsonIgnore ))
#Setter
private password;
}
Recently i had the same issue using jackson-annotation 2.9.0 and lombok 1.18.2
This is what worked for me:
#Getter
#Setter
public class User {
#JsonIgnore
#JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String password;
So basically adding the annotation #JsonProperty(access = JsonProperty.Access.WRITE_ONLY) means that the property may only be written for deserialization (using setter) but will not be read on serialization (using getter)
This could be quite obvious but I lost a lot of time not thinking this solution before:
#Getter
#Setter
public class User {
private userName;
#Setter
private password;
#JsonIgnore
public getPassword() { return password; }
}
As Sebastian said #__( #JsonIgnore ) can resolve this issue but sometimes the use of the onX Lombok feature (#__()) can have side-effects for example breaking the javadoc generation.
I recently had the same issue.
There are several ways to solve it:
Create file lombok.config in the root folder of your project with content:
// says that it's primary config (lombok will not scan other folders then)
config.stopBubbling = true
// forces to copy #JsonIgnore annotation on generated constructors / getters / setters
lombok.copyableAnnotations += com.fasterxml.jackson.annotation.JsonIgnore
...
and in your class you can use this annotation as usual, on the field level:
#JsonIgnore
private String name;
Note: if you use lombok #RequiredArgsConstructor or #AllArgsConstructor, then you should remove all usages of #JsonIgnore with #JsonIgnoreProperties (as described in solution #4, or you may still choose solution #2 or #3). This is required because #JsonIgnore annotation is not applicable for constructor arguments.
Define Getters / Setters manually + add #JsonIgnore annotation on them:
#JsonIgnore
public String getName() { return name; }
#JsonIgnore
public void setName(String name) { this.name = name; }
Use #JsonProperty (it's either read-only or write-only, but no both):
#JsonProperty(access = JsonProperty.Access.READ_ONLY) // will be ignored during serialization
private String name;
#JsonProperty(access = JsonProperty.Access.WRITE_ONLY) // will be ignored during deserialization
private String name;
Use #JsonIgnoreProperties({ "fieldName1", "fieldName2", "..."})
I personally use solution #1 globally and solution #4 for exceptions when class also has annotations #AllArgsConstructor or #RequiredArgsConstructor.
With JDK version 8 use below:
// #Getter(onMethod=#__({#Id, #Column(name="unique-id")})) //JDK7
// #Setter(onParam=#__(#Max(10000))) //JDK7
#Getter(onMethod_={#Id, #Column(name="unique-id")}) //JDK8
#Setter(onParam_=#Max(10000)) //JDK8
Source : https://projectlombok.org/features/experimental/onX

Make Hibernate ignore instance variables that are not mapped [duplicate]

This question already has answers here:
What is the easiest way to ignore a JPA field during persistence?
(10 answers)
Closed 6 years ago.
I thought hibernate takes into consideration only instance variables that are annotated with #Column. But strangely today when I added a variable (that is not mapped to any column, just a variable i need in the class), it is trying to include that variable in the select statement as a column name and throws the error -
Unknown column 'team1_.agencyName' in 'field list'
My class -
#Entity
#Table(name="team")
public class Team extends BaseObject implements Serializable {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
#Column(length=50)
private String name;
#Column(length=10)
private String code;
#Column(name = "agency_id")
private Long agencyId;
private String agencyName; //note: not annotated.
}
FYI...I use the above class in another class with many to many mapping
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(
name="user_team",
joinColumns = { #JoinColumn( name="user_id") },
inverseJoinColumns = #JoinColumn( name="team_id")
)
public Set<Team> getTeams() {
return teams;
}
Why is this happening?!
JPA will use all properties of the class, unless you specifically mark them with #Transient:
#Transient
private String agencyName;
The #Column annotation is purely optional, and is there to let you override the auto-generated column name. Furthermore, the length attribute of #Column is only used when auto-generating table definitions, it has no effect on the runtime.
For folks who find this posting through the search engines, another possible cause of this problem is from importing the wrong package version of #Transient. Make sure that you import javax.persistence.transient and not some other package.
Placing #Transient on getter with private field worked for me.
private String name;
#Transient
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

Problem implementing GET REST service due to JAXBException: IllegalAnnotationExceptions

I am having a really strange problem implementing Java REST service. I am trying receive the following model:
#Data #EqualsAndHashCode(callSuper=false, of={"primaryKey"})
#Entity #Table(name = "T_UNIQUE_IDENT_TYPE")
#Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
#XmlRootElement(name="UniqueIdentifierType") #XmlAccessorType(XmlAccessType.FIELD)
public class UniqueIdentifierType extends AbstractEntityWithTime implements Serializable {
private static final long serialVersionUID = 1L;
#Id #Basic(optional = false) #Column(name = "F_TYPE_PK") #XmlTransient
#GeneratedValue(strategy=GenerationType.SEQUENCE,generator="S_UNIQUE_IDENT_TYPE") #SequenceGenerator(name="S_UNIQUE_IDENT_TYPE",sequenceName="S_UNIQUE_IDENT_TYPE")
private Long primaryKey;
#Column(name = "F_NAME", nullable=false, length=50)
private String typeName;
#Basic(optional = false) #Column(name = "F_CREATION_TIME") #Temporal(TemporalType.TIMESTAMP) #XmlTransient
private Calendar creationTime;
#Basic(optional = false) #Column(name = "F_LASTMODIFY_TIME") #Temporal(TemporalType.TIMESTAMP) #XmlTransient
private Calendar lastModifyTime;
#JoinColumn(name = "F_UNIT_PK", referencedColumnName = "F_UNIT_PK") #ManyToOne(optional = false) #XmlTransient
private SoftwareProviderUnit softwareProviderUnit;
}
My GET rest service has the following signature:
#GET
#Path("/{name}")
public UniqueIdentifierType get(#PathParam("unitId") final Long unitId, #PathParam("name") final String name) throws WebApplicationException {
Whenever I do a call on this GET service I receive 500 error containing
java.lang.AssertionError: JAXBException occurred : 2 counts of IllegalAnnotationExceptions
I was able to trace it down to the following two errors:
javassist.util.proxy.MethodHandler is an interface, and JAXB can't handle interfaces.
this problem is related to the following location:
at javassist.util.proxy.MethodHandler
at private javassist.util.proxy.MethodHandler com.rp.central.model.UniqueIdentifierType_$$_javassist_21.handler
at com.rp.central.model.UniqueIdentifierType_$$_javassist_21
javassist.util.proxy.MethodHandler does not have a no-arg default constructor.
this problem is related to the following location:
at javassist.util.proxy.MethodHandler
at private javassist.util.proxy.MethodHandler com.rp.central.model.UniqueIdentifierType_$$_javassist_21.handler
at com.rp.central.model.UniqueIdentifierType_$$_javassist_21
The weird thing is that if I change the GET method signature to return a List I get 200 with the JSON view of the object which has all the fields except for the typeName field. I am guessing that the exception is somehow related to that field. I've tried adding explicit getters such as
#XmlElement(name="typeName")
public String getTypeName() {
return typeName;
}
to try to force it to send the typeName, this gets the type name into the "List" version of the GET method but still returns 500 for the non list one. The strange thing is that I have another model which looks exactly the same as this one and works without any problems. I've been banging my head against this for a while now, any help will be greatly appreciated.
Thank you.
The exception clearly says that JAXB can't marshal your UniqueIdentifierType, because the object being marshalled is actually an instance of the class enhanced by Javassist (com.rp.central.model.UniqueIdentifierType_$$_javassist_21), and that class contains a field (added by Javassist) which can't be marshalled. Probably, ehancement is done by your ORM tool.
The most obvious solution is to return a fresh copy of the object.

Categories