0

I implemented org.hibernate.event.spi.PreInsertEventListener interface to populate common fields such as createdTime, modifiedTime, etc. in my entities. I also use Spring Boot Data Repository interfaces to handle REST methods.

POST method to create an entity (E.g., User) is working fine and the User details are getting persisted in the tables. The request body is:

{
    "login": "nagu2",
    "password": "123456",
    "displayName": "Nagu 2",
    "preferences": "Test",
    "userProfile": {
        "firstName": "Nagarajan"
    },
    "userStatus": "USERSTATUS_ACTIVE"
}

However, the Body of the 201 response contains a null value for the fields populated using PreInsertEventListener. The response body is:\

{
  "createdTime": null,
  "updatedTime": null,
  "createdBy": null,
  "updatedBy": null,
  "tenant": 1,
  "login": "nagu2",
  "password": "123456",
  "displayName": "Nagu 2",
  "preferences": "Test",
  "userRoles": null,
  "userProfile": {
    "createdTime": null,
    "updatedTime": null,
    "createdBy": null,
    "updatedBy": null,
    "tenant": 1,
    "firstName": "Nagarajan",
    "middleName": null,
    "lastName": null,
    "dateOfBirth": null,
    "timeZone": null,
    "primaryPhone": null,
    "secondaryPhone": null,
    "primaryEmail": null,
    "secondaryEmail": null
  },
  "lastLoginTime": null,
  "userStatus": "USERSTATUS_ACTIVE",
  "_links": {
    "self": {
      "href": "http://localhost:8080/api/user/6"
    },
    "user": {
      "href": "http://localhost:8080/api/user/6"
    }
  }
}

If I GET the Location URL of the 201 response, I do get all the fields populated with non-null values. The GET response of the Location URL is:

{
  "createdTime": "2019-12-07T11:29:50.000+0000",
  "updatedTime": "2019-12-07T11:29:50.000+0000",
  "createdBy": 1,
  "updatedBy": 1,
  "tenant": 1,
  "login": "nagu2",
  "password": "123456",
  "displayName": "Nagu 2",
  "preferences": "Test",
  "userRoles": [],
  "userProfile": {
    "createdTime": "2019-12-07T11:29:50.000+0000",
    "updatedTime": "2019-12-07T11:29:50.000+0000",
    "createdBy": 1,
    "updatedBy": 1,
    "tenant": 1,
    "firstName": "Nagarajan",
    "middleName": null,
    "lastName": null,
    "dateOfBirth": null,
    "timeZone": null,
    "primaryPhone": null,
    "secondaryPhone": null,
    "primaryEmail": null,
    "secondaryEmail": null
  },
  "lastLoginTime": null,
  "userStatus": "USERSTATUS_ACTIVE",
  "_links": {
    "self": {
      "href": "http://localhost:8080/api/user/5"
    },
    "user": {
      "href": "http://localhost:8080/api/user/5"
    }
  }
}

Setting RepositoryRestConfiguration.setReturnBodyOnCreate to true as suggested in this SO question did not help too.

Can you please help me with a way to return non-null values for the PreInsertEventListener-modified-fields in the 201 response of the POST request?

nagu
  • 877
  • 10
  • 17

1 Answers1

1

Following point from This SO Question and this blog post

If you have insert and update actions on your entity in one single transaction, then your preInsert listener actions will be overridden by the update action.

helped me resolve the issue.

Point to be noted here is that:

In onPreInsert method, when I updated only the values in Object[] state, it caused both insert and update query to fire. However, when I set the values in both Object[] state and the entity (event.getEntity()), hibernate fired only the insert query and 201 response JSON contains non-null values.

Following is the modified onPreInsert implementation:

public boolean onPreInsert(PreInsertEvent event) {
    if (event.getEntity() instanceof BaseEntity) {
        Object obj = event.getEntity();
        BaseEntity entity = (BaseEntity) obj;
        boolean isMultiTenant = event.getEntity() instanceof BaseMultiTenantEntity;
        Object[] state = event.getState();
        String[] propertyNames = event.getPersister().getEntityMetamodel().getPropertyNames();

        Date createdTime = new Date();
        entity.setCreatedTime(createdTime);
        setValue(state, propertyNames, CREATED_TIME_PROPERTY, createdTime);

        Integer createdBy = getUserId();
        entity.setCreatedBy(createdBy);
        setValue(state, propertyNames, CREATED_BY_PROPERTY, createdBy);

        entity.setUpdatedTime(createdTime);
        setValue(state, propertyNames, UPDATED_TIME_PROPERTY, createdTime);

        entity.setUpdatedBy(createdBy);
        setValue(state, propertyNames, UPDATED_BY_PROPERTY, createdBy);

        if (isMultiTenant) {
            BaseMultiTenantEntity multiTenantEntity = (BaseMultiTenantEntity) obj;
            multiTenantEntity.setTenant(getTenant());
        }
    }
    return false;
}
nagu
  • 877
  • 10
  • 17