Include null field values in Jersey REST Response - rest

I'm including Instance of Following class in one of my REST Resource Response.
public class GenericResponse<T> implements Serializable {
private String message;
private String errorMessage;
private String errorCode = "0";
....
}
There are other fields in this class but, when a field is null or "0" (as a String), they are being omitted in the Client's Response.
How to include all fields in the Client's REST response even though they are null/empty/0
Additional Information:
Jersey Version: 2.6

I solved this with the Annotation
#JsonInclude(Include.ALWAYS)
on
GenericResponse

Related

REST Api Spring boot with mongodb how to get json?

#GetMapping("/getAccount")
public Account validateAccount(#RequestBody) {
}
Very new to spring boot. My account file has 5+ values all strings, username, password, id, and some etc things.
Given this
{
"username": "bob"
"password": "password"
}
It should give this with 200 response code OK
{
"id": "45645646546"
"username": "bob"
"password": "password"
"status": "Single"
"filler": "filler"
}
However I'm not sure how to read the "username" and "password" json in my validateAccount function
Not really related to this question but does anyone know how to send a response code in the function? Like .sendresponseheader(400) something like that
public class AccountDTO {
#JsonIgnore
private Long id;
#NotNull
private String username;
#NotNull
private String password;
#JsonIgnore
private String status;
#JsonIgnore
private String filler;
// getters & setters
}
You may want to create a DTO (Data Transaction Object) as shown above. Here's a link to it's wiki.
Next pass map user input into this DTO using #RequestBody annotation.
#RestController
public class AccountController {
#GetMapping("/accounts")
public ResponseEntity<Account> validateAccount(#RequestBody AccountDTO accountDTO) {
return new ResponseEntity<>(accountService.validate(accountDTO), HttpStatus.OK);
}
}
Or you can use
#RestController
public class AccountController {
#GetMapping("/accounts")
public Response validateAccount(#RequestBody AccountDTO accountDTO) {
return new ResponseEntity().ok(accountService.validate(accountDTO));
}
}
The user input will be converted from json to AccountDTO using whatever JSON processor your're using most probably it'll be com.fasterxml.jackson.core.
The #JsonIgnore and #NotNull annotation will ensure only username and password fields are used and others are ignored while taking input from user.
You can pass this DTO to your service classes and use something like findByUsername() in your Business Logic and return populated AccountDTO using the below mapper function or some external libraries like Model Mapper or MapStruct.
public toAccountDTO(Account account) {
AccountDTO accountDTO = new AccountDTO();
accountDTO.setUsername(account.getUsername());
// and so on...
return accountDTO;
}
And for your last query, wrap the returned AccountDTO object in ResponseEntity wrapper to provide a proper Response Code with your payload. Here's a link to ResponseEntity Java docs.
AccountDto.java
===============
class AccountDto{
private Long id;
private String username;
private String password;
private String status;
private String filler;
//getters & setters
}
#GetMapping("/getAccount")
public ResponseEntity validateAccount(#RequestBody AccountDto accountDto) {
return new ResponseEntity<>(accountServie.validate(accountDto),HttpStatus.OK);
}
You can do your custom operations before returning the response. Take a look Best Practice of REST
For json response nothing specific just mark class with #RestController.
For #RequestBody just use a pojo to bind the values
For error code and status you can use ResponseEntity

Optional path-parameter in jersey 2.6 sub-resource without constant-part-path

I have 2 almost identical sub-resources:
#GET
#Path("/{device}/{property}")
#Produces(MediaType.APPLICATION_JSON)
public Response getParameterValue(#PathParam("device") final String device,
#PathParam("property") final String property) {
...
}
and
#GET
#Path("/{device}/{property}/{field}")
#Produces(MediaType.APPLICATION_JSON)
public Response getFieldValue(#PathParam("device") final String device,
#PathParam("property") final String property,
#PathParam("field") final String field ) {
...
}
that I want to replace with a single one using regular expressions. I saw among other related many articles about this for example this post and this one on SO.
So I was almost sure to achive my goal writting the sub-resource like so:
#GET
#Path("/{device}/{property}{p:/?}{field:([a-zA-Z][a-zA-Z0-9_]*)?}")
#Produces(MediaType.APPLICATION_JSON)
public Response getParameterOrFieldValue(#PathParam("device") final String device,
#PathParam("property") final String property,
#PathParam("field") final String field ) {
...
}
Unfortunately if a value is present for the field path-parameter:
http://localhost:8080/my-rest/v1/device001/property001/field001
, I got:
HTTP 405 Method Not Allowed
But if there is no value for field:
http://localhost:8080/my-rest/v1/device001/property001
it works fine.
I than introduced a constant part 'just2C' in the path of the sub-resource:
#GET
#Path("/just2C/{device}/{property}{p:/?}{field:([a-zA-Z][a-zA-Z0-9_]*)?}")
#Produces(MediaType.APPLICATION_JSON)
public Response getParameterOrFieldValue(#PathParam("device") final String device,
#PathParam("property") final String property,
#PathParam("field") final String field ) {
...
}
it works in both cases: with or without a value for the path-parameter 'field'.
I'd like to undestand why?
I am using jersey2.6

BSON ObjectID (Morphia) representation in Typescript/Angular2 Project

I have a Java class representing a customer with some properties like name, adress etc.
And I have the property:
#Id
#Property("_id")
private ObjectId id;
The customer will be fetched from a mongoDB. Everything is fine and all properties are filled.
Then I try to transport data via REST to a angular2 client
I have a Customer representation in typescript
export class Customer {
public id: string <---
Mapping inside rest call in client
.map((response: Response) => <Customer> response.json())
what do I need to put here, that the property will be mapped and that I can use it within the angular client.
I've tried to install bson-objectid via npm, but I have no idea how to get it to map the id property. All the others are working fine.
Solution found!
Create a
public YourAdapterName extends XMLAdapter<String, ObjectID> {
#Override
public String marshal(ObjectId v) throws Exception {
return v.toString();
}
#Override
public ObjectId unmarshal(String v) throws Exception {
return new ObjectId(v);
}
}
This Adapter returns the string representation of the ObjectID and I can use
id: string
in Typescript.

(JDBI/Dropwizard) PSQLException when retrieving auto-incremented id from PostgreSQL

I'm trying to set up a dropwizard project but I'm stuck. When I try to get the auto generated id field with #GetGeneratedKeys then I'm getting the following Exception:
org.postgresql.util.PSQLException: Bad value for type long : foo.
The request is a simple JSON Request
{"name":"foo"}
The INSERT into the database is successful but it seems that the statement returns the value of the name instead of the generated id. How can I solve this?
I use postgresql, and the table project contains a primary key field "id" with nextval('project_id_seq'::regclass). Here are the POJO, DAO and Resource Classes I use:
public class Project {
private long id;
private String name;
public Project() { // Jackson deserialization }
public Project(long id, String name) {
this.id = id;
this.name = name;
}
...
}
#RegisterMapper(ProjectMapper.class)
public interface ProjectDAO {
#SqlUpdate("insert into project (name) values (:name)")
#GetGeneratedKeys
public long insert(#Bind("name") String name);
}
#Path("/project")
#Consumes({MediaType.APPLICATION_JSON})
#Produces({MediaType.APPLICATION_JSON})
public class ProjectResource {
ProjectDAO projectDAO;
public ProjectResource(ProjectDAO personDAO) {
this.projectDAO = personDAO;
}
#POST
#Timed
public Response add(#Valid Project project) {
long newId = projectDAO.insert(project.getName());
project.setId(newId);
return Response.status(Response.Status.CREATED)
.entity(project).build();
}
}
===============
UPDATE
I just figured out that this relates to the fact that my id column isn't the first column in my table. The column name is. The problem occurs because #GetGeneratedKeys is using org.skife.jdbi.v2.sqlobject.FigureItOutResultSetMapper which is using org.skife.jdbi.v2.PrimitivesMapperFactory which returns org.skife.jdbi.v2.util.LongMapper.FIRST. This mapper is calling
java.sql.ResultSet.getLong(1) through the method extractByIndex(...) to retrieve the generated id, which isn't the id in my case...
I'll fix the issue by reorganizing the columns in the database, but I'd like to have a robust implementation if possible: Is there a way to specify the column name of the id column when using the #GetGeneratedKeys Annotation? (The org.skife.jdbi.v2.util.LongMapper class contains a also method called extractByName(...))
This is an issue in the jdbi implementation and is fixed in a newer version as described in https://github.com/jdbi/jdbi/issues/114

javaee 6 rest api named query result

I have a simple JEE6 rest class that gets the data from db2. I am using Jackson in ApplicationConfig class to convert the entity objects to json. It converts with the field names as the key and the value as the right hand value. So for example:
Class Entity {
String name;
String address;
}
converts to
{name:"hello", address:"world"}
The service is as follows:
public List<T> findAll() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
Now I want to only return the name in json format. So I created a named query as follows in the entity class:
#NamedQuery(name = "justGetName", query = "SELECT a.name FROM Applications a")
And the service changed to
public List<T> findAll() {
return getEntityManager().createNamedQuery("justGetName").getResultList();
}
This returns the following array:
[{"first","second","third"}]
But I want to get back:
[{name:"first",name:"second",name:"third"}]
How do I write the named query so that the class field names are added to the json structure? Thank you.
You querying a list of strings from your database and this is what the service returns.
Their are multiple ways to achieve your goal.
Pure JPA
Using #JsonIgnore to tell Jackson not to serialize an attribute
class Application {
String name;
#JsonIgnore
String address;
}
Create a new Entity class that only contains the attributes you would like to share
class ApplicationName {
String name;
}
Alternatively you could introduce a separate class that only contains the attributes you would like to share and convert the results from the query into this class and return than the list of this converted values.