Ebean doesn't work with jakson annotation in java - java

I have class:
#Entity
#Data
#Builder(toBuilder = true)
#AllArgsConstructor
#NoArgsConstructor
public class Users extends Model {
#Id
private String id;
private String fullName;
private String country;
private Role role;
public enum Role {
USER;
#Override
#DbEnumValue
public String toString() {
return name().toLowerCase();
}
}
}
It's work good but if I add Jackson annotation #JsonFormat(shape = OBJECT) for enum I have error
#Entity
#Data
#Builder(toBuilder = true)
#AllArgsConstructor
#NoArgsConstructor
public class Users extends Model {
#Id
private String id;
private String fullName;
private String country;
private Role role;
#JsonFormat(shape = OBJECT)
public enum Role {
USER;
#Override
#DbEnumValue
public String toString() {
return name().toLowerCase();
}
}
}
Error:
Caused by: io.ebean.config.BeanNotEnhancedException: Bean class ...Users is not enhanced? Check packages specified in ebean.mf. If you are running in IDEA or Eclipse check that the enhancement plugin is installed. See https://ebean.io/docs/trouble-shooting#not-enhanced
at io.ebeaninternal.server.deploy.BeanDescriptorManager.setEntityBeanClass(BeanDescriptorManager.java:1569)
at io.ebeaninternal.server.deploy.BeanDescriptorManager.createByteCode(BeanDescriptorManager.java:1434)
at io.ebeaninternal.server.deploy.BeanDescriptorManager.readDeployAssociations(BeanDescriptorManager.java:1343)
at io.ebeaninternal.server.deploy.BeanDescriptorManager.readEntityDeploymentAssociations(BeanDescriptorManager.java:761)
at io.ebeaninternal.server.deploy.BeanDescriptorManager.deploy(BeanDescriptorManager.java:365)
at io.ebeaninternal.server.core.InternalConfiguration.<init>(InternalConfiguration.java:208)
at io.ebeaninternal.server.core.DefaultContainer.createServer(DefaultContainer.java:120)
at io.ebeaninternal.server.core.DefaultContainer.createServer(DefaultContainer.java:36)
at io.ebean.EbeanServerFactory.createInternal(EbeanServerFactory.java:109)
at io.ebean.EbeanServerFactory.create(EbeanServerFactory.java:70)
Use ebean - 12.1.10, jakson - 2.10.1
Can you help me, how I can resolve this problem

Related

getting object by parameter from nested object mongodb spring data jpa

I have mongodb collection for following documents:
#Builder
#Data
#AllArgsConstructor
#NoArgsConstructor
#Document
public class Account {
#Id
private String id;
#Indexed(unique=true)
private String username;
#Indexed(unique=true)
private String email;
#Indexed(unique=true)
private String contact;
private ConfirmationTokenDetails confirmationTokenDetails;
}
#Builder
#Data
#AllArgsConstructor
#NoArgsConstructor
#Document
public class ConfirmationTokenDetails {
#Indexed(unique=true)
private String confirmationToken;
private LocalDateTime createdAt;
private LocalDateTime expiredAt;
}
Basically all what I want is just get Account entity by confirmationToken attribut which stores in nested ConfirmationTokenDetails object. I tried do that by using following method
public interface AccountRepository extends MongoRepository<Account, String> {
Optional<Account> findByConfirmationTokenDetails_ConfirmationToken(String token);
}
but it wasn't working for me.

Error when mapping classes with attribute that has foreign key

I have the Hardware entity, HardwareDtoRequest and HardwareDtoResponse classes, where I'm using the modelMapper to map them. In the Hardware table, there is a foreign key to the Provider table.
The problem is that I am not able to map this attribute to HardwareDtoRequest, when I call the POST method in Postman passing only the provider_id in the request body it saves only one record with that particular ID, when trying to save again another record with the same ID it updates the old one.
How do I map this foreign key attribute to the DtoRequest and save?
Hardware.java
#Getter
#Setter
#Entity
public class Hardware {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(nullable = false, length = 100)
private String name;
#ManyToOne
#JoinColumn(name = "provider_id")
private Provider provider;
}
Provider.java
#Getter
#Setter
#Entity
public class Provider {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(nullable = false, length = 100)
private String name;
}
HardwareDtoRequest.java
#Getter
#Setter
#ToString
#AllArgsConstructor
#NoArgsConstructor
public class HardwareDtoRequest {
#NotNull(message = "required field")
private String name;
#NotNull(message = "required field")
private Long providerId;
}
HardwareDtoResponse.java
#Getter
#Setter
#ToString
#AllArgsConstructor
#NoArgsConstructor
public class HardwareDtoResponse {
private Long id;
private String name;
private ProviderDtoResponse provider;
}
HardwareMapper.java
public HardwareDtoResponse toHardwareDtoResponse(Hardware hardware) {
return mapper.map(hardware, HardwareDtoResponse.class);
}
public Hardware toHardware(HardwareDtoRequest hardwareDtoRequest) {
return mapper.map(hardwareDtoRequest, Hardware.class);
}
HardwareService.java
#Transactional
public HardwareDtoResponse save(HardwareDtoRequest hardwareDtoRequest) {
Hardware hardware = mapper.toHardware(hardwareDtoRequest);
Hardware saveHardware = hardwareRepository.save(hardware);
return mapper.toHardwareDtoResponse(saveHardware);
}
HardwareController.java
#PostMapping
public ResponseEntity<HardwareDtoResponse> save(#Valid #RequestBody HardwareDtoRequest hardwareDtoRequest) {
log.info("saving hardware: {}", hardwareDtoRequest);
HardwareDtoResponse hardware = hardwareService.save(hardwareDtoRequest);
return new ResponseEntity<>(hardware, HttpStatus.CREATED);
}
I managed to solve it, for those who have the same problem of mapping dtos with modelMapper, I use the following snippet in ModelMapperConfig:
#Configuration
public class ModelMapperConfig {
#Bean
public ModelMapper mapper() {
ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
return modelMapper;
}
}
You can try to set provider manually. Like this:
public Hardware toHardware(HardwareDtoRequest hardwareDtoRequest) {
Hardware hardware = mapper.map(hardwareDtoRequest, Hardware.class);
Provider provider = providerRepository.findById(hardwareDtoRequest.providerId);
hardware.setProvider(provider);
return hardware;
}

How do I include a related object when serving JSON in Spring?

I have this basic controller method:
#GetMapping
List<Employee> all() {
return employeeRepository.findAll();
}
By default, it seems to serve the JSON representation of Employee just fine, except there's one problem: there's no associated Department in the JSON output.
I've googled and googled and googled, and I can't seem to find an answer.
Employee:
#Entity
#Getter
#Setter
public class Employee {
#Id
#GeneratedValue
private Long id;
#NotNull
private String firstName;
#NotNull
private String lastName;
#NotNull
#Column(unique = true)
private String emailAddress;
#ManyToOne
#JsonBackReference
private Department department;
private String phoneNumber;
}
Department
#Entity
#Getter
#Setter
public class Department {
#Id #GeneratedValue private Long id;
private String name;
#OneToMany(mappedBy="department")
#JsonManagedReference
private Set<Employee> employees;
}
Your issue is probably the mix with JPA.
As you are already using Lombok (#Getter, #Setter).
You can do this:
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Employee {
private Long id;
private String firstName;
private String lastName;
private String emailAddress;
private Department department;
private String phoneNumber;
}
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Department {
...
}

Java Repository Query findAll() given an ID from another class (Foreign-Key)

I'm using a JPARepository called PublicationRepository and want to find all Publications from a certain Person. This Classes are connected over the Class Author.
Person Class:
#Entity
public class Person {
#Id
private String email;
private String telefon;
private String password;
#OneToMany(mappedBy = "person")
Set<Author> Author;
}
Author Class:
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Author {
#Id
private int id;
#ManyToOne
#JoinColumn(name="Person_ID")
Person person;
#ManyToOne
#JoinColumn(name="Publication_ID")
Publication publication;
private String Date;
private String Writerstatus;
}
Publication Class
#Entity
#AllArgsConstructor
#NoArgsConstructor
#Data
public class Publication {
#Id
private int id;
private String publicationname;
#OneToMany(mappedBy = "publication")
Set<Author> author;
}
And the PublicationRepository
public interface ProjektRepository extends JpaRepository<Projekt,Integer> {
}
public interface PublicationRepository extends JpaRepository<Publication,Integer> {
#Query(value = "SELECT pub.* FROM author as auth INNER JOIN publications as pub ON auth.publication_id = pub.id WHERE auth.person_id = ?1", native = true)
List<Publication> findAllPublicationsOfThisPerson(int personId);
}
Try this.
I would also recommend to annotate the entities with their table names:
#Table(name = "publication")
You use a manually build table for a Many-to-Many relationship Author
You could also delegate that to Spring Data Jpa by using #ManyToMany Annotation.
A good tutorial:
https://attacomsian.com/blog/spring-data-jpa-many-to-many-mapping

Spring Rest. Eliminate json property at HTTP.POST

I'm trying to exclude the possibility of a json field to be modificated at HTTP.POST operation. This is my class:
#Data
#Builder
#AllArgsConstructor
#NoArgsConstructor
public class UserModel {
#JsonProperty(access = JsonProperty.Access.READ_ONLY)
private Long userId;
#NotNull
private String username;
private RoleModel role;
#NotNull
private String email;
#NotNull
private String firstName;
#NotNull
private String secondName;
#JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String password;
#JsonProperty(access = JsonProperty.Access.READ_ONLY)
private Date registrationDate;
}
I want for example the property userId to be accessible only for read (http get).
I've tried with #JsonProperty but it doesn't work, instead it works for the password field. (this property is visible only for write/ post).
Can you please tell me where I'm wrong? or if there is a more elegant way to do that?
Many thanks,
You can achieve such thing with #JsonView annotation:
// Declare views as you wish, you can also use inheritance.
// GetView also includes PostView's fields
public class View {
interface PostView {}
interface GetView extends PostView {}
}
#Data
#Builder
#AllArgsConstructor
#NoArgsConstructor
public class UserModel {
#JsonView(View.GetView.class)
private Long userId;
#JsonView(View.PostView.class)
#NotNull
private String username;
....
}
#RestController
public class Controller {
#JsonView(View.GetView.class)
#GetMapping("/")
public UserModel get() {
return ... ;
}
#JsonView(View.PostView.class)
#PostMapping("/")
public UserModel post() {
return ... ;
}
...
}
For more information: https://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring

Categories