Can't use lombok #NoArgsConstructor on a class - java

I'm using Jackson as a Json parser and I'm getting an error:
No suitable constructor found for type ~ can not instantiate from JSON object
So I've tried adding #NoArgsConstructor, but now I'm getting this one:
constructor AccountItem in class AccountItem cannot be applied to given types
Here's my class:
#Getter
#Builder
public class AccountItem {
/**
* Accounti dentifier
*/
private Long accountId;
/**
* Account name
*/
private String accountName;
/**
* Account priority
*/
private int accountPriority;
}
What might be the cause?

Add both #AllArgsConstructor and #NoArgsConstructor annotations to your class

It's known issue from lombok version 1.16.20. https://github.com/rzwitserloot/lombok/issues/1563
You can do this:
#Getter
#Builder
#JsonDeserialize(builder = AccountItem.AccountItemBuilder.class)
public class AccountItem {
/**
* Accounti dentifier
*/
private Long accountId;
/**
* Account name
*/
private String accountName;
/**
* Account priority
*/
private int accountPriority;
#JsonPOJOBuilder(withPrefix = "")
public static final class AccountItemBuilder {
}
}

Related

Initialize objects with Lombok

I have the following object:
#Data
#AllArgsConstructor
#NoArgsConstructor
public class MyComplexObject implements Serializable {
private static final long serialVersionUID = 1L;
private OuputObject ouput;
}
#Data
#AllArgsConstructor
#NoArgsConstructor
public class OuputObject implements Serializable {
private static final long serialVersionUID = 1L;
private InputObject input;
}
#Data
#AllArgsConstructor
#NoArgsConstructor
public class InputObject implements Serializable {
private static final long serialVersionUID = 1L;
private List<String> example;
}
When instantiating the object, the object is not initialized "OuputObject" and is always NULL. Why is the OuputObject object and the InputObject object not instantiated or initialized?
When I do a: getInputObject () I get a NullPointerException
(This is an example, it's fake data)
#Data creates getters and setter, #AllArgsConstructor creates constructor for all the fields, and #NoArgsConstructor creates default constructor. To have your object initialised, you need to use constructor, e.g.
MyComplexObject mco = new MyComplexObject(new InputObject());
Lombok doesn't initialize properties.
The annotation #Data only generates getters and setters for the class properties and overrides the toString, hashCode and equals method.
#Data
public class MyClass {
private String myString;
}
Generates the following code:
public class MyClass {
private String myString;
public String getMyString() {
return myString;
}
public void setMyString(String myString) {
this.myString = myString;
}
// equals, hashcode, toString
}
Have a look at the documentation

How to apply hibernate annotations to the child class of abstract class

I have an abstract class named Staff. Instructor and Lecturer are the derived classes from the Staff superclasses. I need to use hibernate annotations into the Instructor and Lecturer classes.
Staff.java
public abstract class Staff {
private int staffID;
private String firstName;
private String lastName;
private String mobile;
private String email;
private double salary;
private String city;
private String street;
//getters and setters
}
This is the subclass and I used staffID again in the subclass to apply the #Id annotation.
Lecturer.java
#Entity
#Table(name = "lecturer")
public class Lecturer extends Staff {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int staffID;
private int lectureHours;
public int getLectureHours() {
return lectureHours;
}
public void setLectureHours(int lectureHours) {
this.lectureHours = lectureHours;
}
}
I used the service classes and controllers and the JPARepositories as usually. but the database table only contain 2 values fields only (staffID and lectureHours). as follows.
LecturerRepository.java
package com.example.backend.admin.Repositories;
import com.example.backend.admin.models.Lecturer;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface LecturerRepository extends JpaRepository<Lecturer, Integer> {
}
LecturerController.java
#RestController
#RequestMapping("/lecturers")
public class LecturerController {
private static Logger logger = LoggerFactory.getLogger(LecturerController.class);
#Autowired
LecturerService lecturerService;
/**
* to insert a new lecturer
* #param lecturer new lecturer
* #return insert lecturer
*/
#PostMapping("/add")
public Lecturer addLecturer(#RequestBody Lecturer lecturer) {
Lecturer lecturer1 = null;
try {
lecturer1 = lecturerService.addLecturer(lecturer);
} catch (NullPointerException e) {
logger.error("check the payload, null pointer is throwing", e);
}
return lecturer1;
}
}
LecturerService.java
#Service
public class LecturerService {
#Autowired
LecturerRepository lecturerRepository;
/**
* to invoke save method in jpa
* #param lecturer new lecturer
* #return inserted lecturer
*/
public Lecturer addLecturer(Lecturer lecturer){
return lecturerRepository.save(lecturer);
}
}
I want to add all the fields of the Lecturer class into the database. So what should I do for that?
You need to annotate the abstract class with #MappedSuperclass, in this way your #Entity class will inherit all the attributes from the extended class.

How to load data from Database and instance the entity (Hibernate & Spring)

I would like to get objects ResponsableEntity by id from the Database where they are saved. I use Spring-boot and hibernate for the first time and the slouches on other topics don't work in my project
Here are my code :
ResponsableEntity :
#Entity
#Table(name = "responsable")
public class ResponsableEntity {
/**
* Id of the responsable
*/
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
/**
* First name of the responsable
*/
#Column(nullable=false)
private String firstName;
/**
* Lst name of the responsable
*/
#Column(nullable=false)
private String lastName;
/**
* Last latitude of the responsable position
*/
private Double latitude;
/**
* Last longitude of the responsable position
*/
private Double longitude;
/**
* All getters and setters [...]
*/
}
ResponsableDBRepository :
#Repository
public interface ResponsableDBRepository extends CrudRepository<ResponsableEntity, Long> {
}
ResponsableController (REST) :
#RestController
#RequestMapping("/responsable")
public class ResponsableController {
/**
* CRUD Repository atribut needed for the methods below
*/
private final ResponsableDBRepository responsableDBRepository;
private final ResponsableStatDBRepository responsableStatDBRepository;
/**
* Constructor
*
* #param responsableDBRepository CRUD repository for ResponsableEntity
* #param responsableStatDBRepository CRUD repository for ResponsableStatEntity
*/
#Autowired
public ResponsableController(ResponsableDBRepository responsableDBRepository, ResponsableStatDBRepository responsableStatDBRepository){
this.responsableDBRepository = responsableDBRepository;
this.responsableStatDBRepository = responsableStatDBRepository;
}
#GetMapping(path = "/get")
public #ResponseBody String getAllResponsable(){
//get object with id given
return "Returned";
}
}
I'd like that when we call this request, the entity is load from the database and an object ResponsableEntity is created with the infos saved in the database. I already tried most of the answer I found on other topics but most of the time my IDE told me he can't find the class required and it seems to be "default" classes from Hibernate and Spring
Thank you in advance for your answer !
Use this:-
ResponsableEntity responsableEntity = responsableDBRepository.findById(id);

how to set a generic implementation of JpaRepository interface for all entities?

Here is my project structure:
An #MappedSuperclass base class:
#MappedSuperclass
public class BaseClass {
#Id
#GeneratedValue(strategy = GenerationType.TABLE)
private long id;
//getter and setter
}
An #Entity extending the base class:
#Entity
public class Person extends BaseClass {
private String regisNumber;
private String name;
private int hPerWeek;
/**
* #param regisNumber
* #param name
* #param hPerWeek
*/
public Person(String regisNumber, String name, int hPerWeek) {
super();
this.regisNumber = regisNumber;
this.name = name;
this.hPerWeek = hPerWeek;
}
//getters and setters
}
The generic DAO:
#Repository
public interface IDao<T extends BaseClass> extends JpaRepository<T, Long> {
}
In my tests, creating a Person works fine:
#Autowired
IDao<Person> dao;
#Test
public void whenPersonEntityIsCreated_thenNoExceptions() {
Person person = new Person("mkd90ii", "manu", 24);
dao.save(person);
}
Nevertheless trying getting a Person :
#Test
public void whenPersonEntityIsUpdated_thenNoExceptions() {
Person person = dao.getOne(Long.valueOf(32768));
System.out.println(person.toString());
//Updating person...
}
generates me this error:
org.springframework.dao.InvalidDataAccessApiUsageException: Unknown entity: com.bockmoi.entities.BaseClass;
nested exception is java.lang.IllegalArgumentException: Unknown entity: com.bockmoi.entities.BaseClass
I do understand that's because BaseClass is not a javax.persistence.Entity, but why the creation works and not the reading?
Can someone explain me why this happens and how to overcome this?
It's a kind of dead end for me.
Thanks

Constructor method must contain all instance variables

Many times I'm faced with a class which constructor method must contain list of arguments that is identical with the list of class instance variables.
As you see in the example there is "SOME" code to make this hapend.
I'm wondering how can I make this process less painful?
Example:
public class VimeoUser extends Schema {
#Getter #Setter private String uri;
#Getter #Setter private String name;
#Getter #Setter private String link;
#Getter #Setter private String location;
#Getter #Setter private String bio;
#Getter #Setter private String createdTime;
#Getter #Setter private String account;
#Getter #Setter private Map<String,Integer> statistics = new HashMap<>();
#Getter #Setter private List<Website> websites = new ArrayList<>();
#Getter #Setter private List<Portrait> portraits = new ArrayList<>();
public VimeoUser(
String uri,
String name,
String link,
String location,
String bio,
String createdTime,
String account,
Map<String,Integer> statistics,
List<Website> websites,
List<Portrait> portraits){
this.uri = uri;
this.name = name;
this.link = link;
this.location = location;
this.bio = bio;
this.createdTime = createdTime;
this.account = account;
this.statistics = statistics;
this.websites = websites;
this.portraits = portraits;
}
}
It is possible to use a pattern named Builder. It is explained in this question
Basically it works as following:
Create an inner static class Builder
Create a private constructor that take as an argument an object of type Builder
In the Builder class add methods that set a single value and returns this (current reference to instance of the Builder class)
In the body of the constructor of your class use the values passed in the Builder to set each property
add a method build in the Builder that calls the private constructor of your class
Here is an example:
public class NutritionalFacts {
private int sodium;
private int fat;
private int carbo;
public class Builder {
private int sodium;
private int fat;
private int carbo;
public Builder(int s) {
this.sodium = s;
}
public Builder fat(int f) {
this.fat = f;
return this;
}
public Builder carbo(int c) {
this.carbo = c;
return this;
}
public NutritionalFacts build() {
return new NutritionalFacts(this);
}
}
private NutritionalFacts(Builder b) {
this.sodium = b.sodium;
this.fat = b.fat;
this.carbo = b.carbo;
}
}
and to use it do the following:
NutritionalFacts nutritionalFacts = new NutritionalFacts.Builder()
.fat(200).carbo(50).build();
Using this pattern instead of pojo with setter and getter is useful because it is possible to use it also to build immutable objects (objects with all final fields). An immutable object is useful if you need to share it on a multithreaded environment because it is not necessary to synchronize the access to it.
Additionally it is possible to add some controls in the build method to be sure that all fields are setted as expected.
I guess writing pojos for database modelling does not necessarily needs constructor other than default no-arg constructor. If anyway required in some situations, Getters and setters can be used.
Builder pattern
If you want create a object with more readable way, you can use a simple builder pattern. Lombok support this such as #Getter or #Setter. You just add #Builder annotation and everything should works fine.
#Getter
#Builder
public class SomeClass {
private final String valueOne;
private final String valueTwo;
}
And then you can create object in this way.
SomeClass someClass = SomeClass.builder()
.valueOne("one")
.valueTwo("two")
.build();
Fluent accessors method
Alternative way to create a class is using #Accessors annotation with fluent = true. Then you can create a empty object and set the value what you needed in simple way.
#Getter
#Setter
#Accessors(fluent = true)
public class SomeClass {
private String valueOne;
private String valueTwo;
}
Simple sample using this way.
SomeClass someClass = new SomeClass()
.valueOne("one")
.valueTwo("two");
I see you are already using Lombok. There is a #AllArgsConstructor class-level annotation that will generate the constructor for you. If you want the default constructor, too, use #NoArgsConstructor additionally.
More info on the constructor-generating annotations here.

Categories

Resources