I have a Spring Boot application with the following entities:
#Data
#Entity
#Table(name = "jokes")
#EqualsAndHashCode(callSuper = true)
public class Joke extends BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name = "content")
private String content;
}
and
#Data
#MappedSuperclass
public abstract class BaseEntity {
#Column(updatable = false)
#CreationTimestamp
private LocalDateTime createdAt;
#UpdateTimestamp
private LocalDateTime updatedAt;
}
My Controller:
#PostMapping("/jokes")
public Joke createJoke(#Valid #RequestBody Joke joke) {
return jokeRepository.save(joke);
}
The fields createdAt and updatedAt are automatically updated. I am using swagger and when I go on an end point which allows me to create a new resource, then swagger gives me the option of updating the fields createdAt and updatedAt at as well as shown below. The are not actually being updated, but I would like to not see them there. Anyone knows how I could do this?
If you want the fileds to be hidden only at the Swagger level, you can do it with the #Schema annotation of Swagger
#Data
#MappedSuperclass
public abstract class BaseEntity {
#Column(updatable = false)
#CreationTimestamp
#Schema(hidden = true) // One way to do it
private LocalDateTime createdAt;
#UpdateTimestamp
#Schema(accessMode = READ_ONLY) // Other way to do it
private LocalDateTime updatedAt;
}
The difference between the two of them is, hidden will remove the property from Schema component which will make it unavailable for both request and response payloads while accessMode will hide it only for request payloads and not show the access mode in the Schema component as mentioned in the documentation.
accessMode:
Allows to specify the access mode (AccessMode.READ_ONLY, READ_WRITE) AccessMode.READ_ONLY: value will not be written to during a request but may be returned during a response. AccessMode.WRITE_ONLY: value will only be written to during a request but not returned during a response. AccessMode.READ_WRITE: value will be written to during a request and returned during a response.
hidden:
Allows schema to be marked as hidden.
And if you want it to be ignored by the JSON parser that you're using, you'll need something like JsonIgnore if you're using Jackson as the parser.
#Data
#MappedSuperclass
public abstract class BaseEntity {
#Column(updatable = false)
#CreationTimestamp
#JsonIgnore // Jackson will ignore this field
private LocalDateTime createdAt;
#UpdateTimestamp
#JsonIgnore // this will also be ignored
private LocalDateTime updatedAt;
}
Related
I am searching for a better approach, that how to either exclude the auditing fields(like createdBy,createdDate) while fetching the #Entity in Data repository class or ignore them in API response. I know we can do it by using #Ignore or #IgnoreProperties on each property or entity class, but not interested to add it in every class , reason i have too many entities.
Is there any other approach to achieve with simple and with common implementation?
If all auditing fields have the same name, Use an abstract class to manage those fields, then other entirety extend from it;
here is my approach:
#MappedSuperclass
#EntityListeners(AuditingEntityListener::class)
abstract class ModifiedJpaEntity:Serializable {
companion object {
private const val serialVersionUID = -5554308939380869754L
}
#Column
#CreationTimestamp
#JsonIgnore
var createAt:Date?=null
#Column
#CreatedBy
#JsonIgnore
var createBy:String?=null
#Column
#UpdateTimestamp
#JsonIgnore
var updateAt:Date?=null
#Column
#LastModifiedBy
#JsonIgnore
var updateBy:String?=null
val createTimeStr: String
get() = if(createAt!=null) SimpleDateFormat("yyyy-MM-dd HH:mm").format(createAt) else ""
val updateTimeStr: String
get() = if(updateAt!=null) SimpleDateFormat("yyyy-MM-dd HH:mm").format(updateAt) else ""
}
I have two data sources (MySQL and Elasticsearch) configured in a Spring Boot 2.0.2.RELEASE project and JpaAuditing enabled:
#Configuration
#EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
#EnableJpaRepositories("com.example.companies.repository")
#EnableElasticsearchRepositories("com.example.companies.repository.search")
public class DatabaseConfiguration {
}
And I have an entity which I store in both data sources:
#MappedSuperclass
#EntityListeners({AuditingEntityListener.class})
public abstract class AbstractAuditingEntity implements Serializable {
#CreatedBy
private String createdBy;
#CreatedDate
private Instant createdDate = Instant.now();
#LastModifiedBy
private String lastModifiedBy;
#LastModifiedDate
private Instant lastModifiedDate = Instant.now();
}
#Entity
#Table(name = "company")
#Document(indexName = "company")
public class Company extends AbstractAuditingEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
In Elasticsearch I need to have an exact copy of the entity in MySQL (including having the same createdDate and lastModifiedDate):
public Company save(Company company) {
// MySql repository
Company result = companyRepository.save(company);
// Elasticsearch repository
companySearchRepository.save(result);
return result;
}
On create, the entity has the same details in both repositories, but on update, lastModifiedDate receives a different value in the second repository.
Is there an easy way to enable auditing only for one of the two data sources?
Thank you.
I'm using Spring boot with spring data couchbase.
I've added two fields for createdDate and lastModifiedDate with #CreatedDate and #LastModifiedDate annotations in Movie Document.
lastModifiedDate works great but createdDate is always null.
#RequiredArgsConstructor
#NoArgsConstructor
#ToString
#EqualsAndHashCode
#Document
public class Movie {
#Id
#NonNull
#Getter
private String id;
#Getter
#Setter
#NonNull
private String title;
#Getter
#LastModifiedDate
private Date lastModifiedDate;
#Getter
#CreatedDate
private Date createdDate;
}
I've also added a configuration for #EnableCouchbaseAuditing:
#Configuration
#EnableCouchbaseAuditing
public class AuditConfiguration {
}
Movie Repository:
#N1qlPrimaryIndexed
#ViewIndexed(designDoc = "movie")
public interface MovieRepository extends CouchbaseRepository<Movie, String> {
Collection<Movie> findByTitle(String title);
Collection<Movie> findByTitleLike(String title);
Collection<Movie> findByTitleStartingWith(String title);
}
application.yml for reference:
spring:
couchbase:
bootstrap-hosts: localhost
bucket:
name: movie
data:
couchbase:
auto-index: true
As stated in the documentation, in order to distinguish between a creation and an update, spring-data-couchbase needs a #Version annotated attribute in the entity class
If anyone lands here ... I had an issue with the createdDate not being populated even though I followed the spring-data-couchbase documentation. I followed the process of creating immutable objects for my Document and Auditing. The cause was the field annotated with #CreatedDate was final (I used lombok #Value). I had to make it non-final (#NonFinal using Lombok) for it to finally work.
I want to exclude certain fields from a POST to my repositories.
For example I want to set the version myself so users cannot set this field themselves.
For example in the class below.
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#CreatedDate
private LocalDateTime created;
#LastModifiedDate
private LocalDateTime lastModified;
private String name;
}
I have tried to use the #ReadOnlyProperty annotation and not having a setter for the version field. But nothing worked, users can still set the version fields themselves. I have also tried to implement a global initializer like below, but without success. The binder gets picked up though.
#ControllerAdvice
public class GlobalInitializer {
#InitBinder
public void globalBinder(WebDataBinder webDataBinder) {
webDataBinder.setDisallowedFields("name");
}
}
You should place #JsonIgnore on field and on setter, and place #JsonProperty("propertyName") on getter.
Just tested - works for me:
#JsonIgnore
#LastModifiedDate
private LocalDate lastUpdated;
#JsonProperty("lastUpdated")
public LocalDate getLastUpdated() {
return lastUpdated;
}
#JsonIgnore
public void setLastUpdated(LocalDate lastUpdated) {
this.lastUpdated = lastUpdated;
}
I use #Audited annotation in Spring to have auditing about my update, create etc. on my db.
But I obtain on my database, a date-time with 2 hour less than real time, for example, I created a object and the I saved it, I have as create date-time: 2014-08-04 12:0 but I created it at 14:00.
This is my Auditor class, that every class audited extend:
#SuppressWarnings("serial")
#MappedSuperclass
public abstract class AbstractAudit implements Auditable<String, Long>, Serializable {
#Version
private int version;
#JsonIgnore
#Column(updatable=false)
private String createdBy;
#Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
#DateTimeFormat(iso=ISO.DATE_TIME)
#JsonIgnore
#Column(updatable=false)
private DateTime createdDate;
#JsonIgnore
private String lastModifiedBy;
#Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
#DateTimeFormat(iso=ISO.DATE_TIME)
#JsonIgnore
private DateTime lastModifiedDate;
//getter and setter method
}
How can I fix it??
Have I add some configuration on my project or on my server (Tomcat 7) ?
Thanks
Try to set this property in your jpa provider settings:
<prop key="jadira.usertype.databaseZone">jvm</prop>
Hope this helps.
Regards