Set disallowed fields in Spring Data Rest - java

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;
}

Related

Spring boot swagger ui make automatically updated fields invisible

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;
}

Javers #diffIgnore at class/property level not working with inheritance

We are building an application that needs to store differences made on existing opbjects.
Afterwards we will store these changes to the database. However for some reason the #diffIgnore option is not working on our User.class.
Every object extends our baseEntityCMS class, which has a property User. This is meant to store our update user information after the compare by JaVers is done. For some reason the user object is still compared even after setting #diffIgnore on property level and on class level.
Here is the code:
BaseEntityCMS.java
public class BaseEntityCMS extends BaseEntity {
private Boolean active;
private LocalDateTime inactiveDateTime;
private LocalDate creationDate;// in original application
private LocalDate importDate;
private LocalDate startDate;
private LocalDate endDate;
#Embedded
#DiffIgnore
private User modifierUser;
...
}
CodeList.java
public class CodeList extends BaseEntityCMS {
private String companyCode;
private Application sourceApplication;
private String name;
private String format;
private int length;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "codeList")
private List<Description> descriptionList;
#ManyToMany(cascade = CascadeType.ALL, mappedBy = "codeListList")
private List<Keyword> keywords;
private String domainOwner;
#OneToMany(cascade = CascadeType.REFRESH)
private List<Attribute> attributeList;
...
}
User.java
#Embeddable
#AllArgsConstructor
#Builder
#DiffIgnore
public class User {
private String userName;
}
TestCodeList.java
#Test
public void compareCodeListTest() {
Javers javers = JaversBuilder.javers().withListCompareAlgorithm(ListCompareAlgorithm.LEVENSHTEIN_DISTANCE)
.registerValueObject(BaseEntity.class).registerValue(Code.class).registerValue(Attribute.class)
.registerValue(AttributeValue.class).registerValue(MapCodeAttribute.class)
.registerValueObject(User.class).build();
CodeList codeListNew = createCodeListTest("ServiceTest");
CodeList codeListNew2 = createCodeListTest("ServiceTest");
Diff diff = javers.compare(codeListNew2, codeListNew);
assertNull(diff.getChanges());
}
So in the test class we create 2 CodeLists (codeListNew and codeListNew2) with a standard method.
Inside this method everything is created the same except we create a new User every time.
Because all properties of codeList (attribute, attributeValue, ...) extend the BaseEntityCMS class they all have a User property.
This is the output we get:
changes on xxx.CodeList/ :
- 'attributeList' collection changes :
1. 'Attribute(name=Address, format=freeformat, length=10, numberOfDecimals=2, description=description attribute, optional=true)' changed to 'Attribute(name=Address, format=freeformat, length=10, numberOfDecimals=2, description=description attribute, optional=true)'
0. 'Attribute(name=Number of employees, format=freeformat, length=10, numberOfDecimals=2, description=description attribute, optional=true)' changed to 'Attribute(name=Number of employees, format=freeformat, length=10, numberOfDecimals=2, description=description attribute, optional=true)'
- 'mapCodeAttributeMap' map changes :
'Code(super=BaseEntityCMS(super=BaseEntity(id=null), active=true, inactiveDateTime=null, creationDate=2020-03-23, importDate=2020-03-23, startDate=2020-03-23, endDate=2025-12-31, modifierUser=codems.agza.datalayer.model.User#57f83dc7), code=code1)' -> 'MapCodeAttribute(super=BaseEntity(id=null))' added
'Code(super=BaseEntityCMS(super=BaseEntity(id=null), active=true, inactiveDateTime=null, creationDate=2020-03-23, importDate=2020-03-23, startDate=2020-03-23, endDate=2025-12-31, modifierUser=codems.agza.datalayer.model.User#75937998), code=code1)' -> 'MapCodeAttribute(super=BaseEntity(id=null))' removed
We actually expect no difference since everything is the same but the User. This user is marked with #DiffIngore? How come we still have differences?
Forgot: we use
<dependency>
<groupId>org.javers</groupId>
<artifactId>javers-core</artifactId>
<version>5.8.11</version>
</dependency>

Custom json (de)serialize with springboot

It`s possible to create one JsonSerialize and Deserialize with spring boot?
I put in my appliation.properties this line
spring.jackson.date-format=dd/MM/yyyy HH:mm:ss
but when I return one Date he allways returns a wrong value (yyyy-MM-dd) so I try to create one custom serialization following the http://docs.spring.io/spring-boot/docs/1.4.0.RELEASE/reference/htmlsingle/#boot-features-json-components
but don`t work.
this is my return:
#Entity
#Table(name = "view_atos_praticados", catalog="db_registro", schema="db_wsprefeituraatos")
public class ViewAtosPraticados {
#JsonIgnore
#Id
#Column(name="id")
private Integer id;
#Column(name="descricao_ato")
private String ato;
#JsonIgnore
#Column(name="livro")
private String livro;
#JsonIgnore
#Column(name="numero_ato")
private Integer nrAto;
#JsonIgnore
#Column(name="numero_registro")
private String nrRegistro;
#Column(name="dat_registro")
private Date registro;
#Column(name="ic_transmissao")
private String transmite;
Try #JsonFormat annotation:
#JsonFormat(pattern="dd/MM/yyyy HH:mm:ss")
#Column(name="dat_registro")
private Date registro;

Issues saving ZonedDateTime from Dropwizard to MySQL

I'm using dropwizard 0.9.3 to create a simple REST API over MySQL (with Hibernate and Jackson - using Java 8).
I'm hitting a problem when trying to save a UTC DateTime value into a MySQL timestamp column from the application layer - while the application seems to handle it well, the value appearing in the db is a BLOB, so I'm guessing somewhere along the way the serializing the values correctly.
My Entity looks like this:
#Entity
#Table(name = "users")
public class User {
#Id #NotNull #JsonProperty
private String id;
#JsonProperty #NotNull
#Column(name="name", nullable=false)
private String name;
#JsonProperty #NotNull
#Column(name="email", nullable=false)
private String email;
#JsonIgnore #JsonProperty #NotNull
#Column(name="createdAt", nullable = false)
private ZonedDateTime createdAt;
// default constructor
public User() {}
public User(String name, String email) {
this.name = name;
this.email = email;
// get the current UTC timestamp
this.createdAt = ZonedDateTime.now(ZoneOffset.UTC);
}
}
The corresponding DAO is:
public class UserDAO extends AbstractDAO<User> {
public UserDAO(SessionFactory factory) {
super(factory);
}
public User create(User user) {
return persist(user);
}
}
And the Resource is:
#Path("/users")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class UsersResource {
private final UserDAO dao;
public UsersResource(UserDAO dao) {
this.dao = dao;
}
#PUT
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#UnitOfWork
public User create(
#FormParam("name") String firstName,
#FormParam("email") String email
) {
User user = new User(name, email);
return dao.create(user);
}
}
Testing it with a simple curl works, but a BLOB is saved to the DB where the timestamp should be (e.g display a value like 2016-06-28 10:05:22).
I tried to follow the DW conventions, using a fairly conventional bootstrap (and the dropwizard-java8 bundle). I'm not sure what I've missed here, but I'm also new to DW and Java in general.
Suggestions are appreciated - thanks.
DW is using hibernate 5+
For Hibernate to support java time types, you need to inlcude this dependency: (replace with the specific version)
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-java8</artifactId>
<version>5.0.0.Final</version>
</dependency>
Note: this won't save to timestamp type though. Testing with MySQL, it saves to datetime type.
(took this from: Java 8 LocalDateTime and Hibernate 4)
Regards,
artur

Audited wrong date-time in DB

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

Categories