Spring Boot Jackson ResponseEntity No serializer found for class - java

I have an odd error with a spring boot controller, not returning a recently created object.
I have a controller, with 2 methods (see below). One simply retrieves an Object of the class "OrderPay" and returns it as the payload of a response entity. This works fine, the object is therefore okay.
The other one creates and persists a new instance of "OrderPay" and is then supposed to return that newly created object. The creation of the new object and its persistence work fine. However, when I try to return it, I get the error message below.
Now I would understand that error message if it occured consistently. However, when returning this newly created object using the first function ("getPaymentByIdTest"), it returns it without problems, even though I retrieve it in the exact same way from the database and return it in the same way, with the same return type of the method.
Now I know that executing the code in a HTTP-GET method is not best practise, however it is quicker and more convenient for testing.
Can anyone see where I need to adjust the code?
2020-04-13 21:37:57.507 ERROR 26796 --- [nio-8081-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.brownbag_api.model.OrderPay["posSend"]->com.brownbag_api.model.Pos$HibernateProxy$7l7MDMEi["hibernateLazyInitializer"])] with root cause
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.brownbag_api.model.OrderPay["posSend"]->com.brownbag_api.model.Pos$HibernateProxy$7l7MDMEi["hibernateLazyInitializer"])
The Controller
#CrossOrigin(origins = "*", maxAge = 3600)
#RestController
#RequestMapping("/api/pay")
public class PaymentController {
#Autowired
private OrderPayRepo orderPayRepo;
#Autowired
private OrderPaySvc orderPaySvc;
#GetMapping("/{id}")
public ResponseEntity<?> getPaymentByIdTest(#PathVariable Long id) {
Optional<OrderPay> orderPay = orderPayRepo.findById(id);
return ResponseEntity.ok(orderPay);
}
#GetMapping("/exec/from/{from}/to/{to}/amount/{amount}")
public ResponseEntity<?> execPayment(#PathVariable Long from, #PathVariable Long to, #PathVariable double amount) {
Pos posFrom = posRepo.getOne(from);
Pos posTo = posRepo.getOne(to);
OrderPay pay = orderPaySvc.createPay(amount, posFrom, posTo);
pay = orderPaySvc.execPay(pay);
if (pay == null) {
return ResponseEntity.ok("Payment could not be executed. Please see log for more details!");
} else {
System.err.println("Payment executed: " + pay.getPosRcv().getParty().getName());
Long payId = pay.getId();
System.err.println("Payment executed: " + payId);
// payId returns the expected value here, the object is therefore saved in the database (verified).
Optional<OrderPay> orderPay = orderPayRepo.findById(payId);
return ResponseEntity.ok(pay);
}
}
}
Order.java
#Entity
#Table(name = "order_base")
#Inheritance(strategy = InheritanceType.JOINED)
public class Order implements Serializable {
private static final long serialVersionUID = -3458221490393509305L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID")
private Long id;
#NotNull
#Column(name = "QTY")
private double qty;
public Order() {
}
public Order(#NotNull double qty) {
super();
this.qty = qty;
}
}
OrderPay
#Entity
#Table(name = "order_pay")
public class OrderPay extends Order implements Serializable {
private static final long serialVersionUID = 4643589803146964779L;
#NotNull
#OneToOne(targetEntity = Pos.class)
#JoinColumn(name = "POS_SEND_ID")
private Pos posSend;
#NotNull
#OneToOne(targetEntity = Pos.class)
#JoinColumn(name = "POS_RCV_ID")
private Pos posRcv;
public OrderPay() {
super();
}
public OrderPay(#NotNull double qty, #NotNull Pos posSend, #NotNull Pos posRcv) {
super(qty);
this.posSend = posSend;
this.posRcv = posRcv;
}
}
Pos.java
#Entity
#Table(name = "POS")
public class Pos implements Serializable {
private static final long serialVersionUID = 1530699992135610397L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "ID")
private Long id;
#NotNull
#Column(name = "QTY")
private double qty;
#NotNull
#ManyToOne(targetEntity = Party.class)
#JoinColumn(name = "PARTY_ID")
#JsonBackReference
private Party party;
public Pos() {
}
public Pos(#NotNull double qty, #NotNull Party owner) {
super();
this.qty = qty;
this.party = owner;
}
}
JSON
{
"id":7,
"qty":33000.0,
"posSend":
{
"id":1,
"qty":-266010.0,
"hibernateLazyInitializer":{}
},
"posRcv":
{
"id":2,
"qty":66000.0,
"hibernateLazyInitializer":{}
}
}

If you are using Spring Boot, you can set the following property in application.properties file. That should solve the issue according to you stacktrace (see: "to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS")
spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false

Related

Cyclic references when converting with MapStruct. Overflow error. Context does not work

I have 2 entities, with 1-to-1 association (ProfileEntity and VCardEntity)
Entity vcard:
#Entity
#Table(name = "vcard")
#AllArgsConstructor
#NoArgsConstructor
#Data
#SequenceGenerator(name="vcard_id_seq_generator", sequenceName="vcard_id_seq", allocationSize = 1)
public class VCardEntity {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "vcard_id_seq_generator")
#Column(name="vcard_id")
Long id;
String account;
#Column(name = "first_name")
String firstName;
#Column(name = "last_name")
String lastName;
#Column(name = "pbxinfo_json")
String pbxInfoJson;
#Column(name = "avatar_id")
String avatarId;
#OneToOne(mappedBy = "vcard")
ProfileEntity profile;
}
entity Profile:
#Entity
#AllArgsConstructor
#NoArgsConstructor
#Data
#Table(name = "profile")
public class ProfileEntity {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
#Column(name = "profile_id")
private Long profileId;
private String account;
#Column(name = "product_id")
private String productId;
#OneToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "vcard_id", referencedColumnName = "vcard_id")
private VCardEntity vcard;
}
I use map struct as follow:
public class CycleAvoidingMappingContext {
private Map<Object, Object> knownInstances = new IdentityHashMap<Object, Object>();
#BeforeMapping
public <T> T getMappedInstance(Object source, #TargetType Class<T> targetType) {
return targetType.cast(knownInstances.get(source));
}
#BeforeMapping
public void storeMappedInstance(Object source, #MappingTarget Object target) {
knownInstances.put( source, target );
}
}
#Mapper(componentModel = "spring")
public interface EntityToProfile {
ProfileEntity profileToEntity(Profile profile, #Context CycleAvoidingMappingContext context);
Profile entityToProfile(ProfileEntity entity, #Context CycleAvoidingMappingContext context);
}
#Mapper(componentModel = "spring")
public interface EntityToVCard {
VCard entityToVcard(VCardEntity entity, #Context CycleAvoidingMappingContext context);
VCardEntity vcardToEntity(VCard vcard, #Context CycleAvoidingMappingContext context);
}
Finally i call mapping in my service:
#Service
#RequiredArgsConstructor
#Slf4j
public class DefaultChatService implements ChatService {
private final ProfileRepository profileRepository;
private final EntityToProfile entityToProfileMapper;
private final EntityToVCard entityToVCardMapper;
#Override
public List<Profile> findAllProfile(Optional<Long> id) {
if (id.isPresent()) {
Optional<ProfileEntity> result = profileRepository.findById(id.get());
if (result.isPresent()) {
Profile profile = entityToProfileMapper.entityToProfile(result.get(), new CycleAvoidingMappingContext());
return Stream.of(profile).collect(Collectors.toList());
}
}
return new ArrayList<Profile>();
}
}
and i got the error
ERROR 15976 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.StackOverflowError] with root cause
java.lang.StackOverflowError: null
Any thoughts how can i fix it?
In my view i did everything as it's written here Prevent Cyclic references when converting with MapStruct but it doesn't work for me
Found a solution, all i had to do was to change from #Value to #Data for my models
example given:
#Data
public class Profile {
Long profileId;
String account;
String productId;
VCard vcard;
}
and
#Data
public class VCard {
Long id;
String account;
String firstName;
String lastName;
String pbxInfoJson;
String avatarId;
Profile profile;
}
Otherwise mapstruct could not generate proper mapping code. It was trying to store an instance in knownInstances after creating an object, for example Profile. But because #value doesn't provide a way to set properties after creating the object (immutable object) it had to create all settings first and then use all args constructor which led to a mapping profile first which in turn was trying to do the same and map vcard first before storing the VCard object in knownInstances.
This is why the cyclic reference problem could not be solved
Properly generated code:
public Profile entityToProfile(ProfileEntity entity, CycleAvoidingMappingContext context) {
Profile target = context.getMappedInstance( entity, Profile.class );
if ( target != null ) {
return target;
}
if ( entity == null ) {
return null;
}
Profile profile = new Profile();
context.storeMappedInstance( entity, profile );
profile.setAccount( entity.getAccount() );
profile.setProductId( entity.getProductId() );
profile.setDeviceListJson( entity.getDeviceListJson() );
profile.setLastSid( entity.getLastSid() );
profile.setBalanceValue( entity.getBalanceValue() );
profile.setBalanceCurrency( entity.getBalanceCurrency() );
profile.setStatusJson( entity.getStatusJson() );
profile.setData( entity.getData() );
profile.setMissedCallsCount( entity.getMissedCallsCount() );
profile.setFirstCallSid( entity.getFirstCallSid() );
profile.setLastMissedCallSid( entity.getLastMissedCallSid() );
profile.setRemoveToCallSid( entity.getRemoveToCallSid() );
profile.setOutgoingLines( entity.getOutgoingLines() );
profile.setFeatures( entity.getFeatures() );
profile.setPermissions( entity.getPermissions() );
profile.setVcard( vCardEntityToVCard( entity.getVcard(), context ) );
return profile;
}
}
As you can see, firstly, it saves the object in context.storeMappedInstance( entity, profile ); and then fills the properties.

Problem with saving foreign key with #OneToOne annotation. Saving as null

I have two entities (Project, OtherData) with one abstract entity. I'm using MySQL and Quarkus framework.
Problem: When I try to save Project entity field project_id remains null.
Table schemas:
On next picture there is shown, fk constraint in "project_other_data" table:
Abstract Entity:
#MappedSuperclass
public class AbstractEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
protected Long id;
// getters and setters
}
Project Entity
#Entity
#Table(name = "projects")
public class Project extends AbstractEntity {
#NotNull
#Column(name = "name")
private String name;
#NotNull
#Column(name = "surname")
private String surname;
#Column(name = "date_create")
#JsonbDateFormat(value = "yyyy-MM-dd")
private LocalDate dateCreate;
#Column(name = "date_update")
#JsonbDateFormat(value = "yyyy-MM-dd")
private LocalDate dateUpdate;
#OneToOne(mappedBy = "project", cascade = CascadeType.ALL)
private OtherData otherData;
// getters and setters
}
OtherData Entity
#Entity
#Table(name = "project_other_data")
public class OtherData extends AbstractEntity {
#OneToOne
#JoinColumn(name = "project_id")
private Project project;
#Column(name = "days_in_year")
private Integer daysInYear;
#Column(name = "holidays_in_year")
private Integer holidaysInYear;
#Column(name = "weeks_in_year")
private Integer weeksInYear;
#Column(name = "free_saturdays")
private Integer freeSaturdays;
#Column(name = "downtime_coefficient")
private BigDecimal downtimeCoefficient;
#Column(name = "changes")
private Integer changes;
// getters and setters
}
Saving entities with code:
#Path("projects")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class ProjectRest {
#Inject
ProjectService projectService;
#POST
public Response saveProject(Project project) {
return Response.ok(projectService.saveProject(project)).build();
}
}
#RequestScoped
#Transactional
public class ProjectService {
#Inject
EntityManager entityManager;
public Project saveProject(Project project) {
if (project.getId() == null) {
entityManager.persist(project);
} else {
entityManager.merge(project);
}
return project;
}
}
I was able to reproduce the problem by POSTing a new Project with an embedded OtherData. The body I used for the POST:
{
"name": "John",
"surname": "Doe",
"otherData": {}
}
Point is: the database entity is also used as DTO. Thus, the field project in otherData for the request body is set to null (since no Project is passed along this would be a recursive infinite definition).
During processing the entity from the rest controller to the service to the repository, the project of otherData is never set. A quick fix is to modify ProjectService::saveProject as follows:
public Project saveProject(Project project) {
project.getOtherData().setProject(project); // This line was added
if (project.getId() == null) {
entityManager.persist(project);
} else {
entityManager.merge(project);
}
return project;
}
This will fix the database issue (the project_id will be set), but leads to the next issue. The response body cannot be serialized due to an
org.jboss.resteasy.spi.UnhandledException: javax.ws.rs.ProcessingException: RESTEASY008205: JSON Binding serialization error javax.json.bind.JsonbException: Unable to serialize property 'otherData' from com.nikitap.org_prod.entities.Project
...
Caused by: javax.json.bind.JsonbException: Recursive reference has been found in class class com.nikitap.org_prod.entities.Project.
The object structure is cyclic (project references otherData, which return references project, ...) and Jackson is unable to resolve this cycle.
To fix this issue, I would suggest to separate DTOs and database entity and explicitly map between them. In essence:
Structure the Dto-object to represent the JSON-Request and -Response you expect to receive, in a non-cyclic order
Transfer JSON-related annotations from the database entity classes to the DTO classes
In the service- or repository-layer (your choice), map the DTO to the database entites, setting all fields (including the references from project to otherData and vice-versa)
In the same layer, map database-entites back to non-cyclic DTOs
Return the DTOs from the REST endpoint

unable to persist MEDIUMTEXT type field in spring boot

I have a field named 'value' which is of type MEDIUMTEXT in the MySQL db. When I try to persist or fetch the model, it shows
Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction
Model
#Entity
#Table(name = "xyz_something")
#JsonIgnoreProperties(ignoreUnknown = true)
public class Xyz {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#NotBlank(message = "key is mandatory")
#Column(columnDefinition = "CHAR")
#Type(type = "org.hibernate.type.CharArrayType")
private char[] key;
#Column(columnDefinition = "MEDIUMTEXT")
#Type(type = "org.hibernate.type.TextType")
private String value;
// Getters and Setters
Repository
public interface XyzRepository extends JpaRepository<Xyz, Integer> {
}
Controller
#RestController()
#RequestMapping("api/v1")
public class XyzController {
private static Logger logger = LogManager.getLogger();
#Autowired
XyzRepository xyzRepository;
#PutMapping("/xyz")
public HttpStatus insertValue(#RequestHeader(value="id") int id, #NotBlank #RequestBody String value) {
return upsert(value,id);
return HttpStatus.BAD_REQUEST;
}
private HttpStatus upsert(String value, int id) {
return xyzRepository.findById(id)
.map(xyz -> {
xyz
.setKey("key")
.setValue(value);
xyzRepository.save(xyz);
return HttpStatus.CREATED;
}).orElseGet(() -> {
Xyz xyz = new Xyz();
xyz
.setId(id)
.setKey("key")
.setValue(value)
xyzRepository.save(xyz);
return HttpStatus.CREATED;
});
}
}
If I comment out the 'setValue(value)' line, it works, else I get an error mentioned above. I have tried using #Lob with columnDefinition = "MEDIUMTEXT". Also, I have tried putting length in the #Column, that doesn't work as well. What is it that I am doing wrong? Thanks in advance.
It is because you are using a reserved keyword of MySQL i.e. "key". You need to map it using #Column(name = "\"key\"") above your declaration of the field 'key'. You can refer here for more information about reserved keywords.

Am I using OneToOne relationship right?

Hello I am actually working on a REST server using Spring-boot, hibernate, psql and I am experiencing some difficulties after adding an OneToOne relationship between entities.
Here are the 2 entities:
Pays:
#Entity
#Table(name = "pays")
public class Pays implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#JsonProperty("codePays")
private String codePays;
#Column(name = "libelle_pays")
#JsonProperty("libellePays")
private String libellePays;
#OneToOne(mappedBy = "pays",cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional=false)
private Traduction traduction;
protected Pays() {
}
public Pays(String codePays,String libellePays) {
this.codePays = codePays;
this.libellePays = libellePays;
}
and Traduction:
#Entity
#Table(name = "traduction")
public class Traduction implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#JsonProperty("codeTrad")
private long codeTrad;
#Column(name = "defaultLanguage")
#JsonProperty("defaultLanguage")
private boolean defaultLanguage;
#OneToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
#JoinColumn(name="fk_code_pays")
#JsonProperty("codePays")
private Pays pays;
public Traduction(){
}
public Traduction(String codePays,boolean defaultLanguage) {
this.defaultLanguage = defaultLanguage;
pays.setCodePays(codePays);
}
My problem happen when I try to populate my table traduction using a Post method:
#PostMapping("/traduction")
public Traduction createTraduction(#RequestBody Traduction trad) {
System.err.println(trad);
return repository.save(trad);
}
when I send JSON data to my server via PostMan like this:
{
"codeTrad":0,
"defaultLanguage":true,
"fk_code_pays":"FR"
}
or this way:
{
"codeTrad":0,
"defaultLanguage":true,
"pays":
{
"codePays":"FR",
"libellePays":"France"
}
}
My server doesn't seem to understand the mapping with the object Pays.
Here what the object Traduction look like after my request:
[codeTrad=0, null, defaultLanguage=true]
and the pretty error:
Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: (was java.lang.NullPointerException); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.auchan.corp.ipon.iponportail.model.Traduction["codePays"])]
So I am wondering if the problem comes from my server conception or just my JSON. Do you have an idea?
Your issue comes from :
public Traduction(String codePays, boolean defaultLanguage) {
this.defaultLanguage = defaultLanguage;
pays.setCodePays(codePays)
The pays is null and that's why you get an exception : java.lang.NullPointerException, well try to add Pays pays to that constructor.
This json won't work:
{ "codeTrad":0, "defaultLanguage":true, "fk_code_pays":"FR" }
as there is no field name fk_code_pays in your Traduction class.
Below won't work either:
{ "codeTrad":0, "defaultLanguage":true, "pays": { "codePays":"FR", "libellePays":"France" } }
Because pays is annotated with #JsonProperty("codePays")
As per your DTO classes, your json should be:
{ "codeTrad":0, "defaultLanguage":true, "codePays": { "codePays":"FR", "libellePays":"France" } }
Also I would recommend you to use wrapper classes in place of primitives. Boolean in place of boolean and Long in place of long.

Jackson Custom Deserializer Not Working In Spring Boot

I created a custom deserializer for my entities but it keeps on throwing exception:
I have two classes: AppUser and AppUserAvatar
AppUser.java
#Entity
#Table(name = "user")
public class AppUser implements Serializable {
#Transient
private static final long serialVersionUID = -3536455219051825651L;
#JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
#Column(name = "password", nullable = false, length = 256)
private String password;
#JsonIgnore
#Column(name = "is_active", nullable = false)
private boolean active;
#JsonIgnore
#OneToMany(mappedBy = "appUser", targetEntity = AppUserAvatar.class, fetch = FetchType.LAZY)
private List<AppUserAvatar> appUserAvatars;
//// Getters and Setters and toString() ////
}
AppUserAvatar.java
#Entity
#Table(name = "user_avatar")
public class AppUserAvatar extends BaseEntityD implements Serializable {
#Transient
private static final long serialVersionUID = 8992425872747011681L;
#Column(name = "avatar", nullable = false)
#Digits(integer = 20, fraction = 0)
#NotEmpty
private Long avatar;
#JsonDeserialize(using = AppUserDeserializer.class)
#JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id", nullable = false)
private AppUser appUser;
//// Getters and Setters and toString() ////
}
AppUserDeserializer.java
package com.nk.accountservice.deserializer;
import com.edoctar.accountservice.config.exception.InputNotFoundException;
import com.edoctar.accountservice.domain.candidate.AppUser;
import com.edoctar.accountservice.service.candidate.AppUserService;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.IOException;
import java.io.Serializable;
public class AppUserDeserializer extends JsonDeserializer implements Serializable {
private static final long serialVersionUID = -9012464195937554378L;
private AppUserService appUserService;
#Autowired
public void setAppUserService(AppUserService appUserService) {
this.appUserService = appUserService;
}
#Override
public Object deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
Long userId = node.asLong();
System.out.println(node);
System.out.println(node.asLong());
AppUser appUser = appUserService.findById(userId);
System.out.println("appuser: " + appUser);
if (appUser == null) try {
throw new InputNotFoundException("User not found!");
} catch (InputNotFoundException e) {
e.printStackTrace();
return null;
}
return appUser;
}
}
Sample xhr boy is:
{
"appUser": 1,
"avatar": 1
}
An exception is thrown each time I submit the request.
Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: (was java.lang.NullPointerException); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.edoctar.accountservice.domain.candidate.AppUserAvatar["appUser"])]
I discovered that the appUserService.findById() method is not being called. I am really confused. I don't know where I went wrong. Will be greatful for any solution. Thanks.
Updated answer:
You can't use autowired properties because you are not in the Spring context. You are passing the class AppUserDeserializer as a reference in the annotation
#JsonDeserialize(using = AppUserDeserializer.class)
In this situation is the FasterJackson library that creates the instance of AppUserDeserializer, so the Autowired annotation is not taken in consideration.
You can solve your problem with a little trick. Add a static reference to the instance created by spring in the AppUserService:
#Service
public AppUserService {
public static AppUserService instance;
public AppUserService() {
// Modify the constructor setting a static variable holding a
// reference to the instance created by spring
AppUserService.instance = this;
}
...
}
Use that reference in the AppUserDeserializer:
public class AppUserDeserializer extends JsonDeserializer implements Serializable {
private AppUserService appUserService;
public AppUserDeserializer() {
// Set appUserService to the instance created by spring
this.appUserService = AppUserService.instance;
}
...
}
Original answer: To have a correct initialization of an Autowired property you have to annotate your class AppUserDeserializer, otherwise appUserService is null if you don't explicitly init it using the set method.
Try to annotate AppUserDeserializer with #Component:
#Component // Add this annotation
public class AppUserDeserializer extends JsonDeserializer implements Serializable {
...
}
You could go on and try to inject correctly the AppUserService but according to me this is not the cleanest solution. Generally I dislike the idea to use #Entity as communication models or view models. In this way you are coupling the entity to the producer/consumer of the view model. You are basically short-circuiting the model part.
What I would do is to map the contents of the json to a different class in deserialization phase, and use this one later on to construct the corresponding entity.
Try changing this line of code:
private boolean active;
to
private Boolean active;
boolean primitive can't handle nulls and may result in NPE.

Categories