I got a list that return from below db call.
List<employee> list = empolyeeRepository.findByEmployeeId(id);
List contains employee pojo class object. I want to remove one attribute let's say "employee bank account no" when returning from rest call.
#RequestMapping(value = "/employeeInformation/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public List<Employee> getEmployeeInformation(#PathVariable("id") String id) throws Exception {
return empolyeeRepository.findByEmployeeId(id);
}
Is there any annotation or good practice to do that?
As it mentioned in comments above, you cant remove fields of compiled class at runtime. Assuming you have to exclude some field from generated json, there I see two options:
Create a class with fields you want to be present in resulting json, copy required values from original object to a new created. This approach is called view model and allows you to decorate some object's data, hiding sensitive data from being exposed.
Depending on implementation of your serializer there may be annotations to exclude fields. #JsonIgnore may be placed on getter method, if you are using Jackson (default in spring boot). Second aproach requires significant less code, but the first one is more flexible.
Try #JsonIgnore to ignore properties from serialization and de-serialization.
Here is the link to the docs
Related
I will introduce a little bit wider context to clarify my use case...
I would like to implement custom annotation #FilterResponse to annotate JAX-RS method in order to filter fields in JSON response. For latter purpose, I'm using Jacksons's #JsonFilter mechanism. Idea is to enable usage of dot notation to specify wanted fields in whole object graph, starting from returned entity as a root.
For example, if I have method that returns Product entity and I want to return only name field from Product and name field from associated entity CharacteristicValues within a Product, I will do something like this...
#GET
#Produces("application/json")
#Path("/{pid}")
#FilterResponse(include = {"name", "characteristicValues.name"}, responseEntityClass = Product.class)
public Response get(#PathParam("pid") Integer pid) {
Product result = productService.findSimpleProduct(pid);
return Response.ok().entity((result)).build();
}
Under the hood, in interceptor implementation for #FilterResponse annotation, I perform all necessary transformations and configuration of ObjectMapper.
Further, inside interceptor I generate some objects that can be useful in the rest of request processing (in Services, in DAOs, etc), so I would like to pass that objects created in interceptor (for example, my FieldTree object created from metadata specified in #FilterResponse annotation) to intercepted JAX-RS method... And that is my problem right now.
UPDATE: For example, passed FieldTree could be used to reconstruct JPA EntityGraph in order to fetch only preferred fields from database.
Here is pseudo-cod of interceptor to illustrate idea...
#FilterResponse
#Interceptor
public class FilterResponseInterceptor {
#AroundInvoke
public Object intercept(InvocationContext context) throws Exception {
List<String> fieldsToRetain = getIncludeListFromFilterResponseAnottationIn(context);
FeildTree fieldTree = createFieldTreeFrom(fieldsToRetain);
passFieldTreeToMethodInContext(fieldTree, context);
Object response = context.proceed();
return filteredResponseWithFields(response, fieldsToRetain);
}}
When I try to declare paramter which I want to pass to intercepted JAX-RS method from interceptor, as shown below...
#GET
#Produces("application/json")
#Path("/{pid}")
#FilterResponse(include = {"name", "characteristicValues.name"}, responseEntityClass = Product.class)
public Response get(#PathParam("pid") Integer pid, FieldTree requestedFieldTree) {
Product result = productService.findSimpleProduct(pid);
return Response.ok().entity((result)).build();
}
...I'm getting following error...
RESTEASY002010: Failed to execute: javax.ws.rs.NotSupportedException: RESTEASY003200: Could not find message body reader for type: class app.fieldsfiltering.FieldTree of content type: */*
Is there any way to make RESTEasy to ignore some paramters in JAX-RS method, or some other way to perform parameter passing to intercepted JAX-RS method?
Sorry for my lengthily question.
UPDATE2: Some clarifications of my idea... I didn't mention that I would like to avoid "trivial" DTOs that are purely selection of some fields from domain entity without change of the structure. So... EntityGraph for example will be created in DAO or Service layer... But, i feel that "metadata" necessary for EntityGraph creation (e.g. preferred field graph or FieldTree as I called it) should be placed on JAX-RS method. Why? In that case, I would pass FieldTree to Service logic... then, I would create appropriate EntityGraph and eagerly fetch domain entity with all fields defined in FieldTree.. then, I would return domain entity to JAX-RS method and retain only fields defined in FieldTree in JSON response in order to avoid LazyInitialization exception that will be thrown if Jackson try to parse some lazy field in entity object.
I read about ModelMapper, today and it seems to be very interesting, but I'm not sure about the right usage.
I have a Spring-Project like this:
I have my model classes which are necessary for serialization. My REST controller return DTO-objects to the front end. And my frontend returns DTOs to my controller and then I need my model objects from the DTOs to write it to the database.
I have a person class that has an attribute like: Set<Company> companies = new HashSet<Company>();
I want the modelmapper to map this set to an attribute: Set<String> companies = new HashSet<String>().The 2nd set shall be filled by calling companies.getName() instead of filling the Set with the whole object.
My questions:
Do I need a PropertyMap or a converter?
How exactly can I do this?
Is it possible to say Convert from Set<Companies> into a single String. Like I want just one company?
Sorry, I'm very new to ModelMapper and I'm searching for the best way to map during serialization and deserialization in combinatino with spring.
If the name of fields are same in both dto and bean then we can use Spring's BeanUtils class to convert the objects, as shown below:
private UserDto toDto(User user) {
UserDto dto = new UserDto();
BeanUtils.copyProperties(user, dto, new String[]{"companies"});
if (user.getCompanies() != null) {
//Iterate the list and set the company names
}
return dto;
}
BeanUtils belongs to org.springframework.beans package so no dependency is needed. We can pass the array of properties to be ignored as an argument in copyProperties method (like companies in our case) if we want to handle those by ourselves. It uses Reflections and invokes getters and setters to set the values.
In my Spring MVC / Thymeleaf application I apply an UUID when instantiating a brand new instance of any model entity (I do it in an AbstractModel that each entity extends). I use it then for custom equals method implementation that spreads along all entities
#Column(name = "UUID", nullable = false, unique = true)
private String uuid = IdGenerator.createId();
I some other place I create a form bean (simple wrapper) containing a graph of such newly created entities.
an example wrapper would look like this:
WrapperObj obj = new Obj(new FooEntity(), new BarEntity())
both FooEntity and BarEntity have some fileds like ints, Strings etc. that are initially not set. The only fileld that is set isthe UUID
Then I pass the wrapper to the form where I eventually fill up the empty fields.
When I submit the form and the entities are not modified, they still exist in the wrapper. When I attach another object the the wrapper WrapperObj obj = new Obj(new FooEntity(), new BarEntity(), new TestObj()) that has no UUID initially set and submit the form without changing it's fields, the TestObj is reset to null.
This is my desired behaviour for the other UUID-enabled entities.
How can I instruct the spring mvc framework to ignore the UUID field at the binding time so that the entities also become null when not modified?
Thanks for your help!
CORRECTION
the TestObj object was not bound to any input field in the form.
UPDATE
I have just discovered that it is not the uuid that causes the problem. I my wrapper I have another child entity, let's say BoolFoo that has only boolean fields (apart of the id(int) and uuid(string) set by the AbstractEntity class).
Those fields are of type checkbox within the form.
When I submit the form without modifying any of BoolFoo's fileds, BoolFoo as a whole is set to null (although the id and uuid are present when passing the object to the form).
However, if there is at least one text field(did not checked against other types) provided for any child entity, the child object (or any actually) will never be null when comming back from the form.
I've tried already the binder.setDisallowedFields("uuid") approach as well as binder.registerCustomEditor(String.class, new StringTrimmerEditor(true)); but no matter what I do, the unmodified objects will not be set to null.
Looks like there are different rules when it comes to different form field types in spring mvc.
Has anyone come across similar problem?
The DataBinder has two properties named allowedFields and disallowedFields that you could define what to bind or not. Just use that with annotation #InitBinder before executing controller method:
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.setDisallowedFields("uuid");
}
I have a group which contains a list of persons:
class Person {
...
}
class Group {
public Person findPerson(String name) {
...
}
}
Say I have an input JSON (representation of SomeDataClass - see below) which refer to a person by its name:
{
...
"person" : "Bill"
}
I am using Jackson to parse this input JSON. By default, Jackson parses this the person field to a String. Is it possible to change this, such that the person is resolved/looked up during parsing?
class SomeDataClass {
...
#JsonProperty("person")
protected Person person;
}
Note that I do not want to create a new person. I want to look it up, by calling the function getPerson on an instance of Group. This means that I must have access to the group during the parsing. There are several groups at runtime, so it is not singleton.
update
I am aware of the #JsonDeserialize(using = XYZ.cass) possibility, but this does not allow me to pass the group to the custom deserializer. As said, there are multiple groups, so it is not singleton.
I do not think this is possible with Jackson. You could try to store your reference to the group in a ThreadLocal, so your deserializer is using the correct group.
Jackson does have support for Object Ids, via #JsonIdentityInfo annotation. But it is assumed that references using ids ("Bill" in this case) may be resolved by matching definitions within JSON content, so this may not work for your case.
You may need to handle resolution yourself; if you define setPerson(String), method itself could try locating actual instance to use. But that does require use of ThreadLocal, as mentioned.
Another alternative could be custom deserializer, which would use "attribute"s via DeserializationContext; but you still need to provide such mappings so it does not help a lot.
Does naybody knows a way to use Jersey's GET method to return a JSON that returns only some fields of an entity instead of all?
Does anybody know a way to use Jersey's GET method to return a JSON that returns only some fields of an entity instead of all?
E.g. in the following class I want to receive (with POST) values for 'name' and for 'confidential', buy while returning (with GET) I only need 'name' value, not 'confidential'.
#Entity
#Table(name = "a")
#XmlRootElement
#JsonIgnoreProperties({"confifentialInfo"})
public class A extends B implements Serializable {
private String name;
#Basic(optional = false)
private String confifentialInfo;
// more fields, getters and setters
}
If you are using the JAXB approach, you can mark fields with #XmlTransient to omit them. If you are using POJO mapping or want to exclude fields only for some requests, you should construct the JSON with the low level JSON API.
If you are using Jackson, you can use the annotation #JsonIgnore for methods
Marker annotation similar to javax.xml.bind.annotation.XmlTransient
that indicates that the annotated method is to be ignored by
introspection-based serialization and deserialization functionality.
That is, it should not be consider a "getter", "setter" or "creator".
And #JsonIgnoreProperties for properties
Annotation that can be used to either suppress serialization of
properties (during serialization), or ignore processing of JSON
properties read (during deserialization).