How to convert ArrayList to Pageable object springboot - java

I was trying to return list as page object to my client side angular Application. But it return all the list not a page.
this is my server side controller method which return the list
#GetMapping("/users/departmentAdminPageUsers")
#Timed
public ResponseEntity<List<DepartmentAdminPageUserDTO>> getDepartmentAdminPageUsers(#ApiParam Pageable pageable, #ApiParam String searchKey, #ApiParam String depId)
throws URISyntaxException {
List<DepartmentAdminPageUserDTO> userList=userService.getAllDepartmentAdminPageUsers(depId,searchKey);
final Page<DepartmentAdminPageUserDTO> page = new PageImpl<>(userList, pageable,userList.size());
HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/users/departmentAdminPageUsers");
return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
}
this is my client side angular method which send request
getAllUsersByDepId(req?: any):Observable<Response>{
let params: URLSearchParams = new URLSearchParams();
if (req) {
params.set('page', req.page);
params.set('size', req.size);
params.set('searchKey', req.searchKey);
params.set('depId', req.depId);
}
let options = {
search: params
};
return this.http.get(this.resourceUrl+ '/departmentAdminPageUsers', options);
}
I need to return page instead the whole list.

you are returning the whole list as the page content, try:
List<DepartmentAdminPageUserDTO> userSubList = userList.subList((pageable.getPage()-1)*pageable.getSize(), (pageable.getPage()*pageable.getSize())-1);
final Page<DepartmentAdminPageUserDTO> page = new PageImpl<>(userSubList, pageable,userList.size());

protected Page<T> listToPage(Pageable pageable, List<T> entities) {
int lowerBound = pageable.getPageNumber() * pageable.getPageSize();
int upperBound = Math.min(lowerBound + pageable.getPageSize() - 1, entities.size());
List<T> subList = entities.subList(lowerBound, upperBound);
return new PageImpl<T>(subList, pageable, subList.size());
};

Related

Can not access cookie on one endpoint, but can on other

I need your help on this matter. It looks like I have the Schrodinger's cookie!
I am using Spring Boot with Java. I can successfully create the cookie like this:
public String createNewCookie(HttpServletResponse response) {
// create a cookie
String newToken = AccountsService.generateRandomCode(6);
Cookie cookie = new Cookie("clrToken", newToken);
cookie.setMaxAge(10 * 365 * 24 * 60 * 60); // expires in 10 years
cookie.setSecure(true);
cookie.setHttpOnly(true);
//add cookie to response
response.addCookie(cookie);
return newToken;
}
I can easily fetch created cookie and read its value (token) in one of my controllers like this:
#PostMapping(value = "/public/save",
produces = MediaType.APPLICATION_JSON_VALUE)
#Operation(summary = "Save new affiliate click into database")
public ResponseEntity<AffiliateClickDto> saveAffiliateClick
(#RequestParam Long serviceId,
#CookieValue(value = "clrToken", defaultValue = "") final String token) {
return new ResponseEntity<>(affiliateClickService.saveAffiliateClick(serviceId, token), HttpStatus.OK);
}
But I can not fetch that same cookie from another endpoint in my other controller.
#GetMapping(value = "/public/servicesByFilters",
produces = MediaType.APPLICATION_JSON_VALUE)
#Operation(summary = "Get all Providers Services for filters")
public ResponseEntity<List<ServiceResultPageDTO>> getAllProvidersServicesForFilters
(#RequestParam final Map<String, String> params,
#CookieValue(value = "clrToken", defaultValue = "") final String token) {
return new ResponseEntity<>(services.getAllProvidersServiceForFilters(params, token), HttpStatus.OK);
}
I get an empty String for The String token parameter value.
I allso tried to use the loop to iterate through cookies, but I do not get my "clrToken" at this second endpoint. I can access some other cookies.
public String readAllCookies(HttpServletRequest request) {
String token="";
Cookie[] cookies = request.getCookies();
for (Cookie c : cookies) {
if (Objects.equals(c.getName(), "clrToken")) {
token = c.getValue();
break;
}
}
return token;
}
Who eat my cookie??? :D Does anyone have idea what is happening here? If you need some other info, please ask.

Ending an "infinite" stream when certain conditions are met

I'm trying to pull data from a REST-style web-service which delivers content in pages.
The only way I can know that I've reached the end is when I ask for a page and there are no results. I'd like to terminate the stream at that time.
I've written the following Java code. The first function pulls a single page from the web-service and returns it as a stream. The second function flatmaps the streams together into a single stream.
public Stream<ApplicationResponse> getApplications(String token, RestTemplate rt, Integer page, Integer pageSize) {
HttpEntity<String> entity = new HttpEntity<>("parameters", getHeaders(token));
String url = String.format("%s?PageIndex=%s&PageSize=%s", endpoint, page, pageSize);
ResponseEntity<ApplicationCollection> ar = rt.exchange(url, HttpMethod.GET, entity, ApplicationCollection.class);
ApplicationResponse[] res = Objects.requireNonNull(ar.getBody()).getData();
// Do something here when res is empty, so that the stream ends
return Arrays.stream(res);
}
public Stream<ApplicationResponse> getApplications(String token, RestTemplate rt) {
// This function does the right thing, exept when we run out of data!
return IntStream.iterate(1, i -> i + 1).mapToObj(i -> getApplications(token, rt, i, 500)).flatMap(Function.identity());
}
The problem is, how do I allow this to end?
If I were writing this in Python I'd raise a StopIteration exception at the point where I know there's nothing left to put onto the stream. Is there something similar I can do?
The best thing I could think of was use a null, or raise an exception to signify the end of data and then wrap up the stream into an Iterator that knows to stop when that signal is received. But is there anything more idiomatic that I can do?
After comments from Holger, I gave it a shot and tried Spliterator instead of Iterator. It is indeed simpler, as next and hasNext are... kinda combined into tryAdvance? It is even short enough to just inline it into a util method, imo.
public static Stream<ApplicationResponse> getApplications(String token, RestTemplate rt)
{
return StreamSupport.stream(new AbstractSpliterator<ApplicationResponse[]>(Long.MAX_VALUE,
Spliterator.ORDERED
| Spliterator.IMMUTABLE)
{
private int page = 1;
#Override
public boolean tryAdvance(Consumer<? super ApplicationResponse[]> action)
{
HttpEntity<String> entity = new HttpEntity<>("parameters", getHeaders(token));
String url = String.format("%s?PageIndex=%s&PageSize=%s", endpoint, page, 500);
ResponseEntity<ApplicationCollection> ar = rt.exchange(url, HttpMethod.GET, entity,
ApplicationCollection.class);
ApplicationResponse[] res = Objects.requireNonNull(ar.getBody()).getData();
if (res.length == 0)
return false;
page++;
action.accept(res);
return true;
}
}, false).flatMap(Arrays::stream);
}
You could implement an Iterator and create a Stream of it:
public class ResponseIterator
implements Iterator<Stream<ApplicationResponse>>
{
private int page = 1;
private String token;
private RestTemplate rt;
private ApplicationResponse[] next;
private ResponseIterator(String token, RestTemplate rt)
{
this.token = token;
this.rt = rt;
}
public static Stream<ApplicationResponse> getApplications(String token, RestTemplate rt)
{
Iterable<Stream<ApplicationResponse>> iterable = () -> new ResponseIterator(token, rt);
return StreamSupport.stream(iterable.spliterator(), false).flatMap(Function.identity());
}
#Override
public boolean hasNext()
{
if (next == null)
{
next = getNext();
}
return next.length != 0;
}
#Override
public Stream<ApplicationResponse> next()
{
if (next == null)
{
next = getNext();
}
Stream<ApplicationResponse> nextStream = Arrays.stream(next);
next = getNext();
return nextStream;
}
private ApplicationResponse[] getNext()
{
HttpEntity<String> entity = new HttpEntity<>("parameters", getHeaders(token));
String url = String.format("%s?PageIndex=%s&PageSize=%s", endpoint, page, 500);
ResponseEntity<ApplicationCollection> ar = rt.exchange(url, HttpMethod.GET, entity,
ApplicationCollection.class);
ApplicationResponse[] res = Objects.requireNonNull(ar.getBody()).getData();
page++;
return res;
}
}
It will check whether the next response is empty in hasNext(), stopping the stream. Otherwise, it will stream and flatMap that response. I have hardwired pageSize, but you can easily make that a third input for the factory method ResponseIterator.getApplications().

Spring MVC - How do I return a view in a ResponseEntity method?

I have a problem.
I don't know how to return a view in a method with a return type of ResponseEntity.
I want to download a file with my controller.
The download works fine if a file was uploaded.
If no file were uploaded, it just should do nothing (return the actual view).
Now I´m not sure how to do this because I guess it's not possible returning a view (For that I needed return-type String).
Do you have any idea?
#Controller
public class FileDownloadController {
#RequestMapping(value="/download", method = RequestMethod.GET)
public ResponseEntity fileDownload (#Valid DownloadForm form, BindingResult result) throws IOException{
RestTemplate template = new RestTemplate();
template.getMessageConverters().add(new FormHttpMessageConverter());
HttpEntity<String> entity = new HttpEntity<String>(createHttpHeaders("test.jpg", "image/jpeg"));
UrlResource url = new UrlResource("www.thisismyurl.com/images" + form.getImageId());
return new ResponseEntity<>(new InputStreamResource(url.getInputStream()), createHttpHeaders("test.jpg", "image/jpeg"), HttpStatus.OK);
}
private HttpHeaders createHttpHeaders(String filename, String contentType) {
HttpHeaders headers = new HttpHeaders();
headers.setAll(getHttpHeaderMap(filename, contentType));
return headers;
}
private Map<String,String> getHttpHeaderMap(String filename, String contentType) {
Map<String, String> headers = new HashMap<>();
headers.put("Content-disposition", "attachment; filename=\"" + filename + "\"");
headers.put("Content-Type", contentType);
return headers;
}
}
Hi i had a similar problem in my project once, i.e., I have to different return types view vs string based on some logic.
First it’s definitely not possible to return a model and view when you have response entity as return type.
I solved this using generic return type
public <T> T fileDownload (#Valid DownloadForm form, BindingResult result) throws IOException{
//your code
//here you can return response entity or
//modelAndView based on your logic
}
I've found that this works with Spring Boot 2 and JSP views:
#GetMapping(value = "/view/theobject/{id}")
public Object getDomainObject(ModelAndView mav, #PathVariable Long id) {
Optional<DomainObject> theObject = svc.getDomainObject(id);
if (theObject.isPresent()) {
mav.setViewName("viewdomainobject");
mav.addObject("theObject", theObject.get());
return mav;
}
return ResponseEntity.notFound().build();
}
There's no need for the unpleasant <T> T generic return type, or casting the returned object.

Spring AngularJS get request

I am trying to do pagination for my users list. I have an error "Bad request" when I try to use params in request. What can be the problem?
UserController.java
#RequestMapping(value = "/user/{page}",params ={"size"}, method = RequestMethod.GET)
public ResponseEntity<List<User>> getList(#PathVariable("page") int page, #RequestParam("size") int size) {
List usersList = userService.getList(page, size);
ResponseEntity<List<User>> respEntity = null;
if(usersList.isEmpty()){
respEntity =new ResponseEntity<List<User>>(HttpStatus.NO_CONTENT);
return respEntity;
}
respEntity =new ResponseEntity<List<User>>(usersList, HttpStatus.OK);
return respEntity;
}
user_service.js
fetchAllUsers: function(page, size) {
return $http.get('http://localhost:8080/user/' + page, size)
.then(
function(response){
console.log(response.data);
console.table(response.data);
return response.data;
},
function(errResponse){
console.error('Error while fetching users');
return $q.reject(errResponse);
}
);
},
The documentation of $http.get says:
get(url, [config]);
[...]
config (optional) Object Optional configuration object
You're passing the size as second argument, instead of a config object. The correct code is
$http.get('http://localhost:8080/user/' + page, {
params: {
size: size
}
})...

How to ajax in spring mvc and tile

Is there any way integrate ajax in spring mvc and apache tile. For me, when sent the request to controller and after that send back to view, the data can not pass through tile config.
Help me please. Thanks
I do this all the time. What i do is, instead of sending back a "View" string or "ModelAndView" object, return an object of type ResponseEntity.
For instance, in your controller class, you can have a method like:
#RequestMapping(value="/cache/clear", method = RequestMethod.GET)
public ResponseEntity<String> clearAllCaches() {
Map<String, Object> results = new HashMap<String, Object>();
long startTimestamp = System.currentTimeMillis();
for (CachingService cachingService : cachingServices) {
LOGGER.info("Clearing caches in " + cachingService.getClass().getSimpleName());
cachingService.clearCache();
}
long finishTimestamp = System.currentTimeMillis();
long executionTime = finishTimestamp - startTimestamp;
LOGGER.warn("Finished clearing caches in " + cachingServices.size() + " services in " + executionTime + " ms.");
results.put("executionTime", executionTime);
results.put("serviceCount", cachingServices.size());
results.put(ServiceConstants.RETURN_KEY_SUCCESS, Boolean.TRUE);
return createResponse(results, HttpStatus.CREATED);
}
protected ResponseEntity<String> createResponse(Map <String, Object> results, HttpStatus successCode) {
JSONSerializer serializer = new JSONSerializer();
String responseBody = serializer.deepSerialize(results);
HttpStatus status = successCode;
boolean success = results.containsKey(ServiceConstants.RETURN_KEY_SUCCESS)
? (Boolean)results.get(ServiceConstants.RETURN_KEY_SUCCESS)
: false;
if (!success) {
status = HttpStatus.BAD_REQUEST;
}
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setContentLength(responseBody.length());
headers.add("Access-Control-Allow-Origin", "*");
return new ResponseEntity<String>(responseBody, headers, status);
}
Note that I'm using FlexJSON as I'm using Spring Roo. You could also manually invoke Jackson.
i solve my problem by annotation #ResponseBody to send string back to ajax page.
public #ResponseBody
String test() {
List<User> users = userDetailsService.test();
for (User user : users) {
System.out.println(user);
}
return "1";
}

Categories