I am new to REST API, so I am not sure whether I have phrased the question correctly.
I have a Java class with two attributes.
class TestClass {
private double rate;
private double quantity;
#ApiModelProperty
getRate() {
return rate;
}
#ApiModelProperty
getQuantity() {
return quantity;
}
}
I have an API, which when i call, fetches data from an SQL table and returns a JSON object as shown(I have used examples):
{
rate = 5;
quantity = 10;
}
I want to modify the output so that only either rate or quantity would be displayed depending on the condition. How do i do it?
You can have two API methods that each returns different object
class TestClassRate {
private double rate;
#ApiModelProperty
getRate() {
return rate;
}
}
class TestClassQuantity {
private double quantity;
#ApiModelProperty
getQuantity() {
return quantity;
}
}
what is the condition? if you want to show only not null field, you have to make the correct configuration of your json provider.
For example, if you're using Jackson :
#JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
Related
i'm using java, for example, i have 2 tables staff(id, name, status_id, company_id) and company(id, name), the corresponding entity looks like:
public class Staff {
private Integer id;
private String name;
private Integer statusId;
private Integer companyId;
private Company company;
}
public class Company {
private Integer id;
private String name;
private List<Staff> staffList;
}
for status_id of table staff, 0 means New, 1 represents Active and 2 stands for Inactive.
I need to show New, Active or Inactive on html page/excel when describe a staff status rather than 0, 1 or 2.
And I have a StaffDto:
public class StaffDto {
private Integer id;
private String name;
private Integer statusId;
private String companyName;
}
my questions are:
the statusName(New/Active/Inactive) should be in StaffDto, such that there is no need to calculate status name according to statusId on each client, right?
what is a good practice to get statusName base on statusId?
I should write code like
public class StaffDto {
private Integer statusId;
private String statusName;
public String getStatusName() {
switch(statusId) {
case 0: return "New";
case 1: return "Active";
case 2: return "Inactive";
}
}
}
is this a good practice? or something else(e.g. enum) is better?
if the logic of getting status name is added in StaffDto, what if there is another dtoj(e.g. ADto) also need to show status name, then I have to re-write this logic in ADto?
what if one client need to show New, Active or Inactive, while another client need to show A, B or C or something else, then what should I return in StaffDto? do I still return New, Active or Inactive in StaffDto, and other client need to calculate N, A or I base on statusId on their client? or should I return something else to client instead of xxxDto?
I too would go for enum as you mentioned, bind the status code to the name
then, you do not have to rewrite the logic in DTOs, Make your model have the enum rather than code or name
enum can have its own methods like getShortName for different representations
enum Status {
NEW(0), Active(1), InActive(2);
private final int code;
Status(int code) {
this.code = code;
}
public String getShortName() {
return this.name().substring(0, 1).toUpperCase();
}
public int getCode() {
return code;
}
}
Sorry for bad english.
I currently use dto for request body mapping,
Spring can not know input is null or not received, because both situation is just null.
As an example, Like this.
// dto
public class UpdateDto {
private String name;
private Integer price;
}
// entity
public class Product {
#Id
#GeneratedValue
private Long id;
#Column(nullable = true)
private String name;
#Column(nullable = true)
private Integer price;
}
I solved in string case using empty string. When empty string received, update this field to null. Because most of case empty string can treated as null.
// update name
if (updateDto.getName() != null) {
if (updateDto.getName() == "") {
// set name to null
} else {
// just update to getName() value
}
}
// update price
// when i set to null?
However integer case, I don't know how can i solve this problem.
Anything good idea?
you can use primitive data type int and set nullable as false since null doesn't make sense for numbers
use primitive data type for price in both entity and dto
Entity:
#Column(nullable = false)
private int price;
DTO:
private int price;
I found the easiest solution.
related link(In korean): https://www.it-gundan.com/ko/java/spring-rest-controller%EC%97%90%EC%84%9C-%EB%B6%80%EB%B6%84-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8%EC%97%90-%EB%8C%80%ED%95%B4-null-%EA%B0%92%EA%B3%BC-%EC%A0%9C%EA%B3%B5%EB%90%98%EC%A7%80-%EC%95%8A%EC%9D%80-%EA%B0%92%EC%9D%84-%EA%B5%AC%EB%B3%84%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95/827265839/
the solution is, add dirty check boolean flag in setter.
in case of above,
// dto
public class UpdateDto {
private String name;
private Integer price;
private Boolean isPriceDirty;
// when setter setPrice,
public void setPrice(Integer price) {
this.price = price;
this.isPriceDirty = true;
}
}
then, output can set null only when dirty is true.
I have requirements graph nested query with java resolver.
getAccounts(type: "01",transactionMonths: 12){
accountNumber,
openDate,
productType,
accountTransactions(annualFee: True){
amount,
date
}
}
How can we write query in graphql and how to write java resolver for nested query.
How to fetch the nested query arguments to to pass to my jparepository.
i have Account type and Transactions type as below
type Account{
accountNumber: String
openDate: String
type: String
transactionMonths: String
productType: String
accountTransactions:[AccountTransaction]
}
type AccountTransaction{
amount: String
date:String
annualFee:Boolean
}
How can i retrive the accountTransactions in accounts using nested query using java resolver.
Did you look into implementing a GraphQLResolver as explained for the BookResolver in this link ?
If you read the above link, you should be able to write something like this:
public class AccountResolver implements GraphQLResolver<Account> {
public Collection<AccountTransaction> accountTransactions(Account account,Boolean annualFee) {
// put your business logic here that will call your jparepository
// for a given account
}
}
As for your java DTO, you should have something like this:
public class Account {
private String accountNumber;
private String openDate;
private String type;
private String transactionMonths;
private String productType;
// Don't specify a field for your list of transactions here, it should
// resolved by our AccountResolver
public Account(String accountNumber, String openDate, String type, String transactionMonths, String productType) {
this.accountNumber = accountNumber;
this.openDate = openDate;
this.type = type;
this.transactionMonths = transactionMonths;
this.productType = productType;
}
public String getAccountNumber() {
return accountNumber;
}
public String getOpenDate() {
return openDate;
}
public String getType() {
return type;
}
public String getTransactionMonths() {
return transactionMonths;
}
public String getProductType() {
return productType;
}
}
Let me explain a bit more the code concerning the resolver above:
You create a new resolver for your Account DTO;
It has one method with the exact same signature as your GraphQL field in Account, that is: accountTransactions, returning a collection of AccountTransaction.
As for the Java DTO:
It specify all the fields of your GraphQL type but NOT the field you want your resolver to resolve.
SpringBoot GraphQL will autowire the resolver, and it will be called if the client asked for details on the account and its transactions.
Assuming that you have defined a GraphQL query called accounts that returns all accounts, the following GraphQL query would be valid:
{
accounts {
accountNumber
accountTransactions {
amount
date
annualFee
}
}
}
I am trying to design an API which involves book a transaction to the system. The system will then generate a transaction ID that uniquely identifies the transaction.
I would like to define the Transaction class as a immutable one, like this:
public class Transaction {
private final double quantity;
private final BigDecimal price;
public Order(double quantity, BigDecimal price) {
this.quantity = quantity;
this.price = price;
}
public double getQuantity() {
return quantity;
}
public BigDecimal getPrice() {
return price;
}
}
The client call the API to create a new transaction:
public void storeTransaction(Transaction t)
But if I do this, how can I store the generated transaction ID?
1. Option 1
I can add an mutable state to the transaction class:
public class Transaction {
private final double quantity;
private final BigDecimal price;
private String transactionID;
public Order(double quantity, BigDecimal price) {
this.quantity = quantity;
this.price = price;
}
public double getQuantity() {
return quantity;
}
public BigDecimal getPrice() {
return price;
}
public String getTransactionID() {
return transactionID;
}
public void setTransactionID(String id) {
transactionID = id;
}
}
But this will make the Transaction class mutable.
Option 2
I can keep using the immutable Transaction and expose the API like this:
public String storeTransaction(Transaction t)
So instead of save the transaction id in the Transaction class, I could return it to our API user. But this does not look perfect for me as well because the user has to maintain an ID->Transaction relationship.
What is the best practice for designing this type of scenario?
You can generate the id in your constructor:
public class Transaction {
private final double quantity;
private final BigDecimal price;
private String transactionID;
public Order(double quantity, BigDecimal price) {
this.transactionID = this.generateID();
this.quantity = quantity;
this.price = price;
}
}
Now just implement a generateID() method to fill in the details.
Your storeTransaction() method could return the saved transaction which also contained the id.
public Transaction storeTransaction(Transaction t) {
...
}
And your Transaction class could have two constructors, one with the transaction id (for when it is known) and one without.
Your storeTransaction() method could save transaction with no id is present or if an id was present:
throw an exception if you want to keep your transactions immutable in your database or
update the existing transaction if you don't need immutability in the database.
The storeTransaction() method would return a new Transaction object containing all the details of the saved transaction (if it didn't throw an exception, of course).
Well, finalizing it does not make it that immutable. It is quite easy to change a final field in java, even easier than accessing a private field. Therefore I would create a mutable field, but it's setter does only work if the field is currently null. So you can only set it once (when it's generated). If the field is not null then you can throw an IllegalStateException
I am trying to calculate sum of amount in sql.I am using java POJO classes.Now i am writing query like this
"SELECT SUM(amount) FROM fundraisingusers ";
But it is displaying error as Could not find setter for SUM(amount) on class com.lh.alumni.dto.FundraisingUsers.How to add getter and setter for SUM in my Java pojo class?
Here is my pojo class
public class FundraisingUsers implements Serializable{
private Integer fundraisinguserId;
private BigDecimal amount;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "fundraisinguserId")
public Integer getFundraisinguserId() {
return fundraisinguserId;
}
public void setFundraisinguserId(Integer fundraisinguserId) {
this.fundraisinguserId = fundraisinguserId;
}
#Column(name = "amount")
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
I guess what you are trying to do is, you want to get the sum of all users amount.
The problem here is, you try to get a fundraisingusers-object and assign the amount to the sum of all users amounts to each user. This is wrong.
What you can do is:
SELECT amount FROM fundraisingusers;
and for all models you get you can then build the sum on code-side.
or you could try building a pojo with getter/setter like
private BigDecimal sumamount;
#Column(name = "sumamount")
public BigDecimal getSumAmount() {
return this.sumamount;
}
public void setSumAmount(BigDecimal amount) {
this.sumamount= sumamount;
}
and the query is
SELECT sum(amount) as SumAmount FROM fundraisingusers;