I want to access data from a spring boot service. The return type of the data is a List, but every time I access it, the list is empty.
This is my code:
Map<String, String> params = new HashMap<String, String>();
params.put("firstName", "test" );
params.put("lastName", "test1");
ResponseEntity<Person[]> response = restTemplate.getForEntity(url, Person[].class, params);
In this case, response.getBody() is an empty [].
#RequestMapping(value = "/search", method = RequestMethod.GET)
public List<Person> searchUsers(
#RequestParam(value = "firstName", required = false) String firstName,
#RequestParam(value = "lastName", required = false) String lastName,
#RequestParam(value = "email", required = false) String email {
return personService.search(firstName, lastName, email, company);
}
I also tried with String, and Person[], but nothing worked.
Thanks in advance!
#GET
#Path("statement")
#Produces({MediaType.APPLICATION_XML})
public Response statement(#QueryParam("from") String from, #QueryParam("to") String to) {
DB idb = new DB();
List<Transaction> transactions = idb.getTransactionsByDate(from, to);
final GenericEntity<List<Transaction>> entity = new GenericEntity<List<Transaction>>(transactions) {
};
return Response.status(Response.Status.OK).entity(entity).build();
}
Related
I am creating Spring Boot Web service and I have a Model Employee
public class Employee {
private String id;
private String name;
private String designation;
private int salary;
//Has Getters and Setters
}
I want to create a Get request which will fetching and filter the List of Employees based on the parameters given by user.
For example, if the user gives name of an employee and designation of employee, the get method should filter those result. For various combination of parameters it should work.
#Override
public List<Employee> getEmployees(Map<String, Object> parameters) {
if (parameters.size() == 0)
// code to return all employees;
List<Employee> selectedEmployees = new ArrayList<Employee>();
for(Employee currentEmployee: new ArrayList<Employee>(employee.values())) {
for(Map.Entry<String, Object> check: parameters.entrySet()) {
try {
if(check.getValue() instanceof Integer) {
int condition = (int) Employee.class.getMethod("get" + check.getKey()).invoke(currentEmployee);
if((int) check.getValue() == condition)
selectedEmployees.add(currentEmployee);
} else if (check.getValue() instanceof String) {
String condition = (String) Employee.class.getMethod("get" + check.getKey()).invoke(currentEmployee);
if (((String) check.getValue()).equals(condition))
selectedEmployees.add(currentEmployee);
}
} catch(Exception e){
e.printStackTrace();
}
}
}
return selectedEmployees;
}
In order to avoid multiple if else cases I am filtering list based on String and Integer above.
I think I am making an error in the below code which sending request in Controller.
#RequestMapping(value={"/employees","/{id}/{name}/{designation}/{salary}"})
public List<Employee> getEmployeeByProperty(EmployeeRequestParameters requestParams){
//Map for storing parameters to filter the List
Map<String, Object> filterParams = new HashMap<>();
if(requestParams.getIdParam().isEmpty()) {
filterParams.put("id", Integer.parseInt(requestParams.getIdParam()));
}
if(!requestParams.getNameParam().isEmpty()) {
filterParams.put("name", requestParams.getNameParam());
}
if(!requestParams.getDesignationParam().isEmpty()) {
filterParams.put("designation", requestParams.getDesignationParam());
}
if(requestParams.getSalaryParam().isEmpty()) {
filterParams.put("salary", Integer.parseInt(requestParams.getSalaryParam()));
}
return EmployeeService.getEmployeesByProperty(filterParams);
}
If {id} field is not full, {name} or {designation} or {salary} to be null.For {name} or {designation} or {salary} to be full Because should be {id} full.
#GetMapping("/employees")
public List<Employee> getEmployeeByProperty(#RequestParam(value = "id", required=false) String id,
#RequestParam(value = "name", required=false) String name,
#RequestParam(value = "designation", required=false) String designation,
#RequestParam(value = "salary", required=false) int salary) {
//Your codes
}
Even if {id} is empty, you can use others.
I have the following metod in my #Restcontroller:
#GetMapping
public List<User> getByParameterOrAll(
#RequestParam(value = "email", required = false) String email,
#RequestParam(value = "phone", required = false) String phone) {
List<User> userList;
if ((email != null && !email.isEmpty()) && (phone == null || phone.isEmpty())) {
userList = super.getByEmail(email);
} else if ((email == null || email.isEmpty()) && (phone != null)) {
userList = super.getByPhone(phone);
} else {
userList = super.getAll();
}
return userList;
}
This method allows to handle following GET-requests:
GET: /customers/
GET: /customers?email=emai#email.com
GET: /customers?phone=8-812-872-23-34
But if necessary to add some more parameters for request. If it will be 10 or... 20 params,body of above method arrise outrageously!
If there any way to pass value of #RequestParam to the method-body, I could realize, for example:
#GetMapping
public List<User> getByParameterOrAll(
#RequestParam(value = "any", required = false) String any) {
if (value=="email") {
userList = super.getByEmail(email);
} else if (value=="email") {
userList = super.getByPhone(email);
} else if .....
}
Is there any way to use #RequestParam-value in method-body?
#RequestParam
When an #RequestParam annotation is declared as a Map
or MultiValueMap, without a parameter name specified
in the annotation, then the map is populated with the request
parameter values for each given parameter name.
#GetMapping
public List<User> getByParameterOrAll(#RequestParam Map<String, String> parameters){
....
}
will get you all the parameters and values as a map.
You can't use single #RequestParam for different name-value on the request. Another way for you can be retrieve all #RequestParam of the request like this aswer
You can just add HttpServletRequest as a method parameter and Spring will give it to you:
#GetMapping
public List<User> getByParameterOrAll(#RequestParam(value = "email", required = false)
String email,
#RequestParam(value = "phone", required = false)
String phone, HttpServletRequest request)
Then, you can use the HttpServletRequest API to get the list of parameters passed:
request.getParameterNames() or request.getParameterMap()
See the docs here:
https://docs.oracle.com/javaee/6/api/javax/servlet/ServletRequest.html#getParameterMap()
My problem is I can search from database. But I did searching by using findAll of JpaSpecificationExecutor. But, I want to do searching by using findById and pass my specification, pageable and id to it return page. But it is not working.
Here is my controller:
#GetMapping(value = "/search")
public ResponseEntity<ResponseDTO> allAccountRightService(
#RequestParam(value = "search", required = false) String search,
#RequestParam(value = "page", required = false) Integer page,
#RequestParam(value = "size", required = false) Integer size,
#RequestParam(value = "order", required = false) String order,
#RequestParam(value = "orderBy", required = false) String orderBy) {
ResponseDTO responseDTO = new ResponseDTO("accountRightService List", accountRightService.search(search, page, size, order, orderBy));
return new ResponseEntity<>(responseDTO, HttpStatus.OK);
}
and here is my `service impl` method:
public Map<PageInformation, List<AccountRightDTO>> search(String search, Integer page, Integer size, String order,
String orderBy) {
Map<PageInformation, List<AccountRightDTO>> accountRightList = new HashMap<>();
PageInformation pageInfo = new PageInformation();
if (order == null || order.isEmpty())
order = "DESC";
if (orderBy == null || orderBy.isEmpty())
orderBy = "createdAt";
Pageable pageable = CommonUtil.createPageRequest(page, size, order, orderBy);
Specification<AccountRight> spec = CommonUtil.buildSearchSpecification(search);
//Page<AccountRight> accountRightPage = accountRightRepository.findAllByRightByAppointment(CommonUtil.getAppointment().getAppointmentID(), spec, pageable);
Page<AccountRight> accountRightPage = accountRightRepository.findAll(spec, pageable);
List<AccountRight> accountRights = accountRightPage.getContent();
List<AccountRightDTO> accountRightDTOs = new ArrayList<>();
accountRightDTOs = accountRights.stream().map(accountRight -> {
AccountRightDTO accountRightDTO = new AccountRightDTO();
AppointmentDTO rightToAppointmentDTO = new AppointmentDTO();
AppointmentDTO rightByAppointmentDTO = new AppointmentDTO();
BeanUtils.copyProperties(accountRight, accountRightDTO, "accountRightID");
accountRightDTO.setAccountRightID(Long.toString(accountRight.getAccountRightID()));
BeanUtils.copyProperties(accountRight.getRightToAppointment(), rightToAppointmentDTO, "appointmentID");
rightToAppointmentDTO.setAppointmentID(Long.toString(accountRight.getRightToAppointment().getAppointmentID()));
BeanUtils.copyProperties(accountRight.getRightByAppointment(), rightByAppointmentDTO, "appointmentID");
rightByAppointmentDTO.setAppointmentID(Long.toString(accountRight.getRightToAppointment().getAppointmentID()));
accountRightDTO.setRightByAppointment(rightByAppointmentDTO);
accountRightDTO.setRightToAppointment(rightToAppointmentDTO);
return accountRightDTO;
}).collect(Collectors.toList());
pageInfo.setSize(accountRightPage.getSize());
pageInfo.setTotalElements(accountRightPage.getTotalElements());
pageInfo.setTotalPages(accountRightPage.getTotalPages());
accountRightList.put(pageInfo, accountRightDTOs);
return accountRightList;
}
and this is my buildsearchspecification method
public static <T> Specification<T> buildSearchSpecification(String search) {
SearchSpecificationsBuilder<T> builder = new SearchSpecificationsBuilder<T>();
if (search != null && !search.isEmpty()) {
String[] str = search.split(",");
if (str != null) {
for (String strTemp : str) {
Pattern pattern = Pattern.compile("(\\p{Punct}?)(.*)(:|!|<|>|~)(.*)(\\p{Punct}?),");
Matcher matcher = pattern.matcher(strTemp + ",");
while (matcher.find()) {
builder.with(matcher.group(1), matcher.group(2),
SearchOperation.getSimpleOperation(matcher.group(3).toCharArray()[0]),
matcher.group(4));
}
}
}
}
Specification<T> spec = builder.build();
return spec;
}
and here is my findAllByRightByAppointment repository method
#Query("select account from AccountRight account where account.rightByAppointment.appointmentID=?1")
Page<AccountRight> findAllByRightByAppointment(Long appointmentID, #Nullable Specification<AccountRight> spec, Pageable pageable);
If I use findAll method than searching will work otherwise by using my custom method pagination works without searching
I found an answer by using Specification.Where(your_specification).and(your_search_specification).
here is my updated code now:
Specification<AccountRight> searchSpec = CommonUtil.buildSearchSpecification(search); //this specification needs my search string.
SearchSpecification<AccountRight> rightByAppointmentID =
new SearchSpecification<AccountRight>(new SearchCriteria("rightByAppointment.appointmentID", SearchOperation.EQUALITY, CommonUtil.getAppointment().getAppointmentID())); //this specification accepts search criteria with key, operation and value.
Page<AccountRight> accountRightPage = accountRightRepository.findAll(Specification.where(rightByAppointmentID).and(searchSpec), pageable);
//here you will just tell findAll method to findAll entities where rightByAppointmentID is equal to
//CommonUtil.getAppointment().getAppointmentID() and search query is searchSpec
I have following service method for SMS callback processing
#RequestMapping(value = "/", method = RequestMethod.POST)
#ResponseBody
public void processSms(#RequestParam(value = "MessageStatus", required = false) String messageStatus,
#RequestParam(value = "ApiVersion", required = false) String apiVersion,
#RequestParam(value = "SmsSid", required = false) String smsSid,
#RequestParam(value = "SmsStatus", required = false) String smsStatus,
#RequestParam(value = "To", required = false) String to,
#RequestParam(value = "From", required = false) String from,
#RequestParam(value = "MessageSid", required = false) String messageSid,
#RequestParam(value = "AccountSid", required = false) String accountSid){
TwilioCallBackResponse response = new TwilioCallBackResponse();
response.messageStatus = messageStatus;
response.apiVersion = apiVersion;
response.smsSid = smsSid;
response.smsStatus = smsStatus;
response.to = to;
response.from = from;
response.messageSid = messageSid;
response.accountSid = accountSid;
LOG.info("Incomming twilio callback: " + response.messageStatus);
smsService.processSmsCallback(response);
}
I can get and log response from twilio successfully.
Problem is that in twilio end response error is logged. Should I specify content type or respond with some response body? Any ideas?
This is from twilio log
and error 11200 HTTP retrieval failure is also logged
Status callbacks do not control application flow, so TwiML does not need to be returned in this instance; however, it's recommended that you respond to status callbacks with either a 204 No Content or a 200 OK with Content-Type: text/xml and an empty <Response/> in the body. Failure to respond properly will result in warnings in Debugger.
Ok, based on Jim answer this is what works for me and no more warnings on twilio side
#RequestMapping(value = "/", method = RequestMethod.POST, produces = "text/xml")
#ResponseBody
#ResponseStatus(value = HttpStatus.OK)
public String processSms(#RequestParam(value = "MessageStatus", required = false) String messageStatus,
#RequestParam(value = "ApiVersion", required = false) String apiVersion,
#RequestParam(value = "SmsSid", required = false) String smsSid,
#RequestParam(value = "SmsStatus", required = false) String smsStatus,
#RequestParam(value = "To", required = false) String to,
#RequestParam(value = "From", required = false) String from,
#RequestParam(value = "MessageSid", required = false) String messageSid,
#RequestParam(value = "AccountSid", required = false) String accountSid){
TwilioCallBackResponse response = new TwilioCallBackResponse();
response.messageStatus = messageStatus;
response.apiVersion = apiVersion;
response.smsSid = smsSid;
response.smsStatus = smsStatus;
response.to = to;
response.from = from;
response.messageSid = messageSid;
response.accountSid = accountSid;
LOG.info("Incomming twilio callback: " + JsonUtils.printJson(response));
smsService.processSmsCallback(response);
return "<Response/>";
}
Trying to understand what is wrong with the sending of a Hashmap of values.
Client-side (Angular)
var params = {
year: reportYear,
reportAgg: {
"interest": "Java",
"domain": "JavaCodeGeeks.com"
}
};
return $http.post('test/' + pathVariable1 + '/',
$.param(params), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
Server-Side (Spring/Jackson)
#RequestMapping(value = RqMapping, method = RequestMethod.POST)
public ResponseEntity sendReports(
final #PathVariable(value = "pathVariable1") String organizationId,
final #RequestParam(value = "year", required = true) int requestedYear,
final #RequestParam(value = "reportAgg", required = false) Map<String, String> reportAgg,
final HttpServletRequest request) {
In the request.getParametersMap its possible to see the expected reportAgg[interest] and reportAgg[domain] but still i get a null value for reportAgg in the mapping.
You can use JackSon's ObjectMapper to convert into HashMap
#RequestMapping(value = RqMapping, method = RequestMethod.POST)
public ResponseEntity sendReports(
final #PathVariable(value = "pathVariable1") String organizationId,
final #RequestParam(value = "year", required = true) int requestedYear,
final #RequestParam(value = "reportAgg", required = false) String reportAgg,
final HttpServletRequest request) {
ObjectMapper mapper = new ObjectMapper();
String json = reportAgg;
Map<String, String> map = new HashMap<String, String>();
// convert JSON string to Map
map = mapper.readValue(json, new TypeReference<Map<String, String>>(){});
System.out.println(map ); // out put as HashMap<String, String>
}// end of sendReports()