I have got an array response from the following code.
I am able to return the array result as above but how do i return a json object using one of the values from that array? I am very much new to Java, springboot and hibernate. Any help would be appretiated!
GoalPlanController
#RequestMapping(method = RequestMethod.GET, path="/calculateRecurringAmount")
public ResponseEntity<Object> getCalculateRecurringAmount( String accountID) {
try {
logger.info("get recurring amount by accountid:->", accountID);
AccountsDTO[] goalPlan = goalPlanService.getCalculateRecurringAmount(accountID);
return new ResponseEntity<>(goalPlan, HttpStatus.OK);
}catch(Exception ex) {
logger.error("Exception raised retriving recurring amount using accountId:->" + ex);
ErrorDTO errors = new ErrorDTO();
errors.setError(ex.getMessage());
errors.setStatus(HttpStatus.SERVICE_UNAVAILABLE.value());
return new ResponseEntity<>(errors, HttpStatus.SERVICE_UNAVAILABLE);
}
}
This is GoalPlanDaoImplementation
#Autowired
private GoalPlanRepository goalPlanRepository;
#Override
public List<Accounts> getCalculateRecurringAmount(String accountID) {
// TODO Auto-generated method stub
List<Accounts> goalPlan = null;
goalPlan = goalPlanRepository.getCalculateRecurringAmount(accountID);
return goalPlan.subList(0, 1);
}
GoalPlanRepository ->
public interface GoalPlanRepository extends JpaRepository<GoalPlan, String>{
#Query("select ac from Accounts ac where ac.userId = :accountID")
public List<Accounts> getCalculateRecurringAmount(#Param("accountID") String accountID);
}
I get a array result as follows
{
"accountID": "acc12345",
"accountName": "hellooee",
"accountType": "goalPlanner",
"userId": "abcd",
"bankName": null,
"bankId": null,
"debiitCardNumber": null,
"availableBalance": null,
}
]```
Now using accountID I need to return a json object like this
{
"calculatedGoalAmount": [
{
"goalFrequency": "Monthly",
"goalAmount": 0.4166666666666667,
"fromAccount": "acc12345"
},
{
"goalFrequency": "Quarterly",
"goalAmount": 1.25,
"fromAccount": "acc12345"
}
]
}
My AccountsDTO has folllowing
public class AccountsDTO {
private String accountID;
private String accountName;
private String accountType;
private String userId;
private String bankName;
private String bankId;
private String debitCardNumber;
//getters and setters
}
And initilAmount, goalTimePeriod, goalAmount are the values entered by user.
then i need to calculate
monthly = (goalAmount-initialAmount)/(12*goalTimePeriod)
quarterly = (goalAmount-initialAmount)/(4*goalTimePeriod)
accountId = (got from the response array above)
First You need to create two classes.
CustomResponse Class
public class CustomResponse {
private List<CalculatedGoalAmount> calculatedGoalAmount;
//getters and setters
}
CalculatedGoalAmount Class
public class CalculatedGoalAmount {
private String goalFrequency;
private double goalAmount;
private String fromAccount;
//getters and setters
}
Then inside your getCalculateRecurringAmount method write below code. Note that I have no idea about your AccountsDTO class.
#RequestMapping(method = RequestMethod.GET, path="/calculateRecurringAmount")
public ResponseEntity<Object> getCalculateRecurringAmount( String accountID) {
CalculatedGoalAmount calculatedGoalAmount = null;
CustomResponse customResponse = null;
try {
customResponse = new CustomResponse();
AccountsDTO[] goalPlan = goalPlanService.getCalculateRecurringAmount(accountID);
for (AccountsDTO accountsDTO : goalPlan) {
calculatedGoalAmount = new CalculatedGoalAmount();
calculatedGoalAmount.setFromAccount(accountsDTO.getFromAccount());
calculatedGoalAmount.setGoalAmount(accountsDTO.getGoalAmount());
calculatedGoalAmount.setGoalFrequency(accountsDTO.getFrequency());
customResponse.getCalculatedGoalAmount().add(calculatedGoalAmount);
}
return new ResponseEntity<>(customResponse, HttpStatus.OK);
}catch(Exception ex) {
logger.error("Exception raised retriving recurring amount using accountId:->" + ex);
ErrorDTO errors = new ErrorDTO();
errors.setError(ex.getMessage());
errors.setStatus(HttpStatus.SERVICE_UNAVAILABLE.value());
return new ResponseEntity<>(errors, HttpStatus.SERVICE_UNAVAILABLE);
}
}
Related
I have a base CreateRequest class which I inherit in a couple of children, each responsible for some custom validations:
Base:
public class CreateEventRequest {
#NotEmpty
private String name;
#NotNull
#JsonProperty
private Boolean isPrivate;
}
Child:
public class CreateRegularEventRequest extends CreateEventRequest {
#NotNull
#Future
private LocalDateTime startTime;
#NotNull
#Future
private LocalDateTime endTime;
public LocalDateTime getStartTime() {
return startTime;
}
public LocalDateTime getEndTime() {
return endTime;
}
}
In order to take advantage of the validations, I've tried this:
#PostMapping(value = "/", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<CreateEventResponse> createEvent(HttpEntity<String> httpEntity,
#AuthenticationPrincipal SecuredUser user) {
try {
CreateEventRequest eventRequest = eventRequestFactory.getEventRequestString(httpEntity.getBody());
Set<ConstraintViolation<CreateEventRequest>> violations = validator.validate(eventRequest);
if (!violations.isEmpty()) {
throw new ConstraintViolationException(violations);
}
return new ResponseEntity<>(this.service.createEvent(eventRequest, user), HttpStatus.CREATED);
} catch (ConstraintViolationException e) {
throw e;
} catch (Exception e) {
return ResponseEntity.badRequest().build();
}
}
My factory is:
public CreateEventRequest getEventRequestString(String json) {
try {
String eventTypeRaw = new ObjectMapper().readTree(json)
.get("event_type").asText();
if (!StringUtils.isEmpty(eventTypeRaw)) {
EventType eventType = EventType.valueOf(eventTypeRaw);
if (EventType.REGULAR.equals(eventType)) {
return objectMapper.readValue(json, CreateRegularEventRequest.class);
} else if (EventType.RECURRING.equals(eventType)) {
return objectMapper.readValue(json, CreateRecurringEventRequest.class);
}
}
return null;
} catch (JsonProcessingException e) {
return null;
}
}
This seems really hacky to me and do not scale for future Parent-Child relation, my question is, is there a way to intercept this request to create this child classes and pass it to the controller or some built-in validations to handle this scenario?
Thanks!
Did yo try:
public ResponseEntity<CreateEventResponse> createEvent( #Valid #RequestBody CreateRegularEventRequest reqBody ...) {
..
all the mapping and validation are done automatically
I have a JSON String as below:
"{ \"password\":\"des123\",\"ROU_DATA\":[{\"FORM_RECEIVING_TIME\":\"12:00:00\",\"REMARKS\":\"Redemption of Unit\"}, {\"FORM_RECEIVING_TIME\":\"13:00:00\",\"REMARKS\":\"sALE of Unit\"}] }";
Now I want to extract the Array from it and need to use it as a separate pojo class so that I can iterate over each value..
Now the problem is, when I try to convert the complete String to Map and get the Array value from the map.. It transforms its format to MAp format like:
{FORM_RECEIVING_DATE = 12:00:00, etc..}
However json string should be {"FORM_RECEIVING_DATE": "12:00:00", etc..}
due to the MAp format its now allowing me to parse it using my POJO Class..
Please help to convert it to my JSONFormat ...
**NOTE: Please note that I can only use Jackson **.
CLASS A
ObjectMapper mapper2 = new ObjectMapper();
Map<String, Object> map;
map = mapper2.readValue(json, new TypeReference<Map<String, Object>>(){});
System.out.println("map: " + map.get("ROU_DATA") );
String array = map.get("ROU_DATA").toString();
String json2 = new ObjectMapper().writeValueAsString(array.replace("[", "").replace("]", ""));
String json3 = new ObjectMapper().writeValueAsString(json2);
System.out.println("json2>>" + json2);
System.out.println("json2>>" + json3);
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
// 1. convert JSON array to Array objects
ROU[] pp1 = mapper.readValue("{" + array.replace("=", ":") + "}", ROU[].class);
for (ROU person : pp1) {
System.out.println(person.getRemarks());
}
CLASS B
import com.fasterxml.jackson.annotation.JsonProperty;
public class ROU {
#JsonProperty("FORM_RECEIVING_TIME")
private String formdate;
#JsonProperty("REMARKS")
private String remarks;
public String getFormdate() {
return formdate;
}
public void setFormdate(String formdate) {
this.formdate = formdate;
}
public String getRemarks() {
return remarks;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
}
map.get("ROU_DATA") returns a List object, and the toString() method of List does not generate JSON text.
You don't need to convert back to a JSON text just to get the ROU[] created, just call convertValue(...).
String input = "{ \"password\":\"des123\",\"ROU_DATA\":[{\"FORM_RECEIVING_TIME\":\"12:00:00\",\"REMARKS\":\"Redemption of Unit\"}, {\"FORM_RECEIVING_TIME\":\"13:00:00\",\"REMARKS\":\"sALE of Unit\"}] }";
ObjectMapper mapper2 = new ObjectMapper();
Map<?, ?> json = mapper2.readValue(input, Map.class);
ROU[] pp1 = mapper2.convertValue(json.get("ROU_DATA"), ROU[].class);
for (ROU person : pp1)
System.out.println(person.getRemarks());
Output
Redemption of Unit
sALE of Unit
class A
public class ROU {
#JsonProperty("FORM_RECEIVING_TIME")
private String formdate;
#JsonProperty("REMARKS")
private String remarks;
public String getFormdate() {
return formdate;
}
public void setFormdate(String formdate) {
this.formdate = formdate;
}
public String getRemarks() {
return remarks;
}
public void setRemarks(String remarks) {
this.remarks = remarks;
}
}
class B
public class ObjOuter {
private String password;
#JsonProperty("ROU_DATA")
private List<ROU> rous;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public List<ROU> getRous() {
return rous;
}
public void setRous(List<ROU> rous) {
this.rous = rous;
}
}
json to Object
ObjectMapper mapper = new ObjectMapper();
try {
ObjOuter outer = mapper.readValue(str, ObjOuter.class);
for (ROU rou : outer.getRous()) {
System.out.println(rou.getFormdate());
System.out.println(rou.getRemarks());
}
} catch (IOException e) {
e.printStackTrace();
}
I have two classes PlaylistResource which has a method createPlaylist which takes an object of type PlaylistRequest. I want to create a POST request on localhost:9999/playlists I am using Postman and I am not sure how to pass the object of PlaylistRequest which is request to the method createPlaylist.
#XmlType(propOrder= {"title", "artistSeeds", "numberOfSongs"})
#XmlAccessorType(XmlAccessType.FIELD)
public class PlaylistRequest {
private String title = "";
#XmlElement(name = "seeds")
private List<String> artistSeeds;
#XmlElement (name = "size")
private int numberOfSongs = 0;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public List<String> getArtistSeeds() {
return artistSeeds;
}
public void setArtistSeeds(List<String> artistSeeds) {
this.artistSeeds = artistSeeds;
}
public int getNumberOfSongs() {
return numberOfSongs;
}
public void setNumberOfSongs(int numberOfSongs) {
this.numberOfSongs = numberOfSongs;
}
}
The other class:
#Path("playlists")
public class PlaylistResource implements PlaylistApi {
#Override
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response createPlaylist(PlaylistRequest request) {
if(request == null) {
System.out.println("Was here");
throw new ClientRequestException(new ErrorMessage("no parameter passed."));
}
try {
List<Song> playList = new ArrayList<>();
List<Song> songs = new ArrayList<>();
List<String> artistsIds = new ArrayList<>();
ArtistResource artistsResources = new ArtistResource();
int playlistDefaultSize = 10;
int i = 0;
do {
playList.add(songs.get(i));
i++;
}while( i < playlistDefaultSize);
Playlist playlist = new Playlist();
playlist.setTitle(request.getTitle());
playlist.setSize(songs.size());
playlist.setTracks(playList);
return Response.status(Response.Status.CREATED.getStatusCode()).entity(playlist).build();
} catch (Exception e) {
throw new RemoteApiException(new ErrorMessage(e.getMessage()));
}
}
}
Change this parameter from data class to string,
public Response createPlaylist(PlaylistRequest request) {
to
public Response createPlaylist(String request) {
then convert it using GSON into your data class.
PlaylistRequest request = new Gson().fromJson(request, new TypeToken<PlaylistRequest >(){}.getType());
Simply add a JSON object in Body of request, select Raw Json in Postman and paste the following object:
NOTE: Add a key Content-Type and set its value to application/json in Header of Request
{
"title": "Some title",
"artistSeeds": [
"string1",
"string2"
],
"numberOfSongs": 0
}
HEADER
BODY
I have to show report data for various cases in text-csv format as soon as the user click's on the given uri's.
The given cases are
1)End_Customer Data
2)Incomplete Profiles.
3)Total Connections
Below is the User and LoginUser Models I have.
LoginUser
public class LoginUser {
private String contact;
private String email;
private String address;
private Gender gender;
#Indexed
private String name;
private Date dob;
#Indexed(unique = true)
private String username;
User
public class User extends LoginUser {
public static final String OBJECT_KEY = "APPUSER";
#Id
private String id;
private String[] imageIds;
private String concerns;
private String summary;
private String likings;
private String occupation;
private String religion;
private String education;
private String height;
#GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)
private double[] location;
private INTERESTS[] interests;
private String fcmId;
private List connections;
private List declined;
private List pending;
Below is the Code I have written.
1)For all the Uri,I have used CSV Writer class to write Header data.The Input's supplied to header Data is through Bean's I have created for respective Uri.For Example for End Customer and Incomplete Profiles i have used User Report bean and for Total Connections i have used Connections Report bean as we have to display data for different fields having different headers.
2)Then,I have retrieved all the users from the records using findAll method.
Then for each user we have done the following task based on the cases
a)For End_Customer
1)For Each User,we have retrieved specific user data and set it in User Report bean and finally set the User Report bean to Csv Writer.
b)For Incomplete Profiles
1)For each user,we have checked whether any of the fields is NULL.If this true I have set the user data to User Report Bean and then set finally the User Report Bean to Csv Writer.
c)TotalConnections
For each User,I have checked the Connection Id(Connection Id is a Foreign Key that contains a list of user's id).
For Each Connection Id,I have retrieved the Connected user specific Details and store them in Connections Report Bean.
Below is
UserReport
public class UserReport {
#Indexed
private String name;
#Indexed(unique = true)
private String username;
private String contact;
private String address;
private String email;
private List connections;
private List pending;
private INTERESTS[] interests;
private String occupation;
private Gender gender;
private String region;
ConnectionsReport
public class ConnectionsReport {
#Indexed
private String name;
#Indexed(unique = true)
private String username;
private List connectionName;
private Set mutualInterest;
private List locations;
private String customerAge;
private List connectionAge;
private Gender customerGender;
private List connectionGender;
private String customerAddress;
private List connectionAddress;
Case 1 EndCustomer
#RestController
#RequestMapping("/report")
public class ReportController {
#Autowired
private UserService userService;
#RequestMapping(value = "/endcustomer", method = RequestMethod.GET, produces = "text/csv")
public void endCustomerReport(HttpServletResponse response) {
ICsvBeanWriter csvWriter=null;
int pageSize=2000;
Page<User> users=null;
int page=0;
String csvFileName = "End-customer.csv";
List<String> headerList=null;
Field[] declaredFields=null;
UserReport userReport=new UserReport();
try {
response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", csvFileName));
headerList = new ArrayList<>();
declaredFields = UserReport.class.getDeclaredFields();
for (Field declaredField : declaredFields) {
headerList.add(declaredField.getName());
}
String[] header = headerList.toArray(new String[]{});
csvWriter.writeHeader(header);
/* CsvPreference.STANDARD_PREFERENCE
Ready to use configuration that should cover 99% of all usages.*/
csvWriter = new CsvBeanWriter(response.getWriter(),
CsvPreference.STANDARD_PREFERENCE);
do {
users = userService.getAllUsers(new PageRequest(page,pageSize));
for (User user : users) {
userReport.setName(user.getName());
userReport.setUsername(user.getUsername());
userReport.setContact(user.getContact());
userReport.setAddress(user.getAddress());
userReport.setEmail(user.getEmail());
userReport.setConnections(user.getConnections());
userReport.setPending(user.getPending());
userReport.setInterests(user.getInterests());
userReport.setOccupation(user.getOccupation());
userReport.setGender(user.getGender());
csvWriter.write(userReport, header);
}
page++;
}while (users.hasNext());
}
catch (IOException e){
e.printStackTrace();
}
finally{
if(csvWriter!=null){
try {
csvWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Case 2 Incomplete Profile
#RequestMapping(value = "/incompleteProfiles", method = RequestMethod.GET, produces = "text/csv")
public void incompleteProfiles(HttpServletResponse response) {
ICsvBeanWriter csvWriter=null;
int pageSize=2000;
Page<User> users=null;
int page=0;
String csvFileName = "IncompleteProfiles.csv";
List<String> headerList=null;
Field[] declaredFields=null;
UserReport userReport=new UserReport();
try {
response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", csvFileName));
headerList = new ArrayList<>();
declaredFields = UserReport.class.getDeclaredFields();
for (Field declaredField : declaredFields) {
headerList.add(declaredField.getName());
}
String[] header = headerList.toArray(new String[]{});
csvWriter.writeHeader(header);
/* CsvPreference.STANDARD_PREFERENCE
Ready to use configuration that should cover 99% of all usages.*/
csvWriter = new CsvBeanWriter(response.getWriter(),
CsvPreference.STANDARD_PREFERENCE);
do {
users = userService.getAllUsers(new PageRequest(page,pageSize));
for (User user : users) {
if(user.getName()==null || user.getGender()==null || user.getInterests()==null || user.getImageIds()==null){
userReport.setName(user.getName());
userReport.setUsername(user.getUsername());
userReport.setContact(user.getContact());
userReport.setAddress(user.getAddress());
userReport.setEmail(user.getEmail());
userReport.setConnections(user.getConnections());
userReport.setPending(user.getPending());
userReport.setInterests(user.getInterests());
userReport.setOccupation(user.getOccupation());
userReport.setGender(user.getGender());
}
csvWriter.write(userReport, header);
}
page++;
}while (users.hasNext());
}
catch (IOException e){
e.printStackTrace();
}
finally{
if(csvWriter!=null){
try {
csvWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Case 3 TotalConnections
#RequestMapping(value = "/totalConnections", method = RequestMethod.GET, produces = "text/csv")
public void totalConnections(HttpServletResponse response) {
ICsvBeanWriter csvWriter=null;
int pageSize=2000;
Page<User> users=null;
int page=0;
String csvFileName = "totalConnections.csv";
List<String> headerList=null;
Field[] declaredFields=null;
ConnectionsReport consreport=new ConnectionsReport();
try {
response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", csvFileName));
headerList = new ArrayList<>();
declaredFields = ConnectionsReport.class.getDeclaredFields();
for (Field declaredField : declaredFields) {
headerList.add(declaredField.getName());
}
String[] header = headerList.toArray(new String[]{});
csvWriter.writeHeader(header);
/* CsvPreference.STANDARD_PREFERENCE
Ready to use configuration that should cover 99% of all usages.*/
csvWriter = new CsvBeanWriter(response.getWriter(),
CsvPreference.STANDARD_PREFERENCE);
do {
users = userService.getAllUsers(new PageRequest(page,pageSize));
for (User user : users) {
ArrayList connList=new ArrayList();
Set mutualInterestList=new HashSet();
ArrayList locationList=new ArrayList();
ArrayList ageList=new ArrayList();
ArrayList genderList=new ArrayList();
ArrayList addressList=new ArrayList();
if(user.getConnections()!=null){
consreport.setName(user.getName());
consreport.setUsername(user.getUsername());
List connections=user.getConnections();
Iterator it=connections.iterator();
LocalDate birthdate = new LocalDate(user.getDob()); //Birth date
LocalDate now = new LocalDate(); //Today's date
Period period = new Period(birthdate, now, PeriodType.yearMonthDay());
consreport.setCustomerAge(period.getYears()+"");
while(it.hasNext()) {
String connectionId = (String) it.next();
User connectedUser=userService.get(connectionId);
connList.add(connectedUser.getName());
mutualInterestList.add(connectedUser.getInterests());
genderList.add(connectedUser.getGender());
addressList.add(connectedUser.getAddress());
locationList.add(connectedUser.getLocation());
addressList.add(connectedUser.getAddress());
LocalDate birthdateconnectedUser = new LocalDate(connectedUser.getDob()); //Birth date
Period period1 = new Period(birthdateconnectedUser, now, PeriodType.yearMonthDay());
ageList.add(period1.getYears());
}
consreport.setConnectionName(connList);
consreport.setMutualInterest(mutualInterestList);
consreport.setLocations(locationList);
consreport.setConnectionAge(ageList);
consreport.setCustomerGender(user.getGender());
consreport.setConnectionGender(genderList);
consreport.setCustomerAddress(user.getAddress());
consreport.setConnectionAddress(addressList);
}
csvWriter.write(consreport, header);
}
page++;
}while (users.hasNext());
}
catch (IOException e){
e.printStackTrace();
}
finally{
if(csvWriter!=null){
try {
csvWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Can anyone guide me how can I optimize my code.So that I can make it more efficient and effective in terms of memory and performance.
I have the following JSON to represent the server response for a salt request:
{
"USER":
{
"E_MAIL":"email",
"SALT":"salt"
},
"CODE":"010"
}
And i tried to map it with the following POJO:
public class SaltPOJO {
private String code = null;
private User user = null;
#Override
public String toString() {
return this.user.toString();
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public class User {
private String e_mail = null;
private String salt = null;
#Override
public String toString() {
return this.e_mail + ": " + this.salt;
}
public String getE_mail() {
return e_mail;
}
public void setE_mail(String e_mail) {
this.e_mail = e_mail;
}
public String getSalt() {
return salt;
}
public void setSalt(String salt) {
this.salt = salt;
}
}
}
Now everytime i do this:
Gson gson = new Gson();
SaltPOJO saltPojo = gson.fromJson(json.toString(), SaltPOJO.class);
Log.v("Bla", saltPojo.toString());
The saltPojo.toString() is null. How can i map my JSON into POJO using Gson?
Is the order of my variables important for the Gson mapping?
Is the order of my variables important for the Gson mapping?
No, that's not the case.
How can i map my JSON into POJO using Gson?
It's Case Sensitive and the keys in JSON string should be same as variable names used in POJO class.
You can use #SerializedName annotation to use any variable name as your like.
Sample code:
class SaltPOJO {
#SerializedName("CODE")
private String code = null;
#SerializedName("USER")
private User user = null;
...
class User {
#SerializedName("E_MAIL")
private String e_mail = null;
#SerializedName("SALT")
private String salt = null;
You don't have proper mapping between your getter and setter. If you change your json to something like below, it would work:
{
"user":
{
"email":"email",
"salt":"salt"
},
"code":"010"
}
If you are getting json form third party then unfortunately, you would have to change your pojo or you could use adapter.