Generate a file for Download in Spring

I need to generate a file for download for a user, imagine, you should give a serial number as a text file to your user. After searching I achieve this solution that works perfectly:

1
2
3
4
5
6
7
8
@GetMapping(path = "/file/get", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public ResponseEntity verificationFile() {
 HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.TEXT_PLAIN);
    headers.setContentDispositionFormData("attachment", "test.txt");
 InputStreamResource inputStreamResource = new InputStreamResource(new ByteArrayInputStream("Hello File".getBytes(StandardCharsets.UTF_8)));
 return ResponseEntity.ok().headers(headers).body(inputStreamResource);
}

After calling http://{SERVER-ADDRESS}:{PORT}/file/get, a file with name test.txt that contains Hello File, geting download.

Filter search result of Elasticsearch to only show user data in JHipster

When we generate a project by JHipster, it doesn't manage that users only access to their data. By default, a user can see all data of an entity (You can find a solution by simple google it).
But after we add Elasticsearch to handle our search, we get a new problem. if user search, he can see result from all data that exists otherwise every user must see their data, not more! by default, the search method is something like this that makes a problem:

return StreamSupport.stream(categorySearchRepository.search(queryStringQuery(query))
    .spliterator(), false).collect(Collectors.toList());

And we have to change it to this one to fix the problem: 

1
2
3
4
5
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery().must(queryStringQuery(query));
if (SecurityUtils.isAuthenticated() && !SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN)) {
 queryBuilder = queryBuilder.filter(matchQuery("user.login", SecurityUtils.getCurrentUserLogin().orElse("")));
}
return StreamSupport.stream(categorySearchRepository.search(queryBuilder).spliterator(), false).collect(Collectors.toList());

In that code, we check if the user doesn't have Admin role (), then we add another filter to quryBuilder to limit the search for the current user.
The solution exists at the 21-point sample project on GitHub that I use it for the source of this post (PointsResource.java).

Lombok, Hibernate, and 'StackOverflowError: null' Exception!

I really like Project Lombok, with use of this library you can code cleaner, just look at the sample of  @Data (here) and you give me the right!
But after using @Data on an entity, and use it into another entity (eg a Set of comments of a post), throw an ugly error: java.lang.StackOverflowError: null. @Data is a shortcut for these annotations of Lombok:
  • @Getter
  • @Setter
  • @ToString
  • @RequiredArgsConstructor
  • @EqualsAndHashCode 
And @EqualsAndHashCode makes this error! I found the solution at last comment of this question on StackOverflow:  https://stackoverflow.com/questions/34972895 We should add this line just after at @Data and exclude relational fields from Equals and Hash methods:

@EqualsAndHashCode(exclude="entries")

I used it on my project, Feader, and you can use it as a sample to check it out ( on develop branch); These are my use case classes Feed.java, and FeedEntry.java, FeedEntry use into Feed (like comments and post):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.glinboy.feader.model;

import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

import lombok.Data;
import lombok.EqualsAndHashCode;

@Entity
@Data
@EqualsAndHashCode(callSuper=true, exclude="entries")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Feed extends BaseModel {

 private static final long serialVersionUID = 7720285113632455831L;
 
 @Column(length=50)
 private String title;
 
 @Column(length=256)
    private String link;
    
    @Lob
    private String description;
 
    @ManyToMany
    @JoinTable(name="feed_category",
      joinColumns = @JoinColumn(name = "feed_id", nullable=false),
            inverseJoinColumns = @JoinColumn(name = "category_id", nullable=false))
    private Set<Category> category;

    @OneToMany(mappedBy="feed")
    private Set<FeedEntry> entries;
}


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.glinboy.feader.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;

import lombok.Data;
import lombok.EqualsAndHashCode;

@Entity
@Data
@EqualsAndHashCode(callSuper=true, exclude="feed")
public class FeedEntry extends BaseModel {

 private static final long serialVersionUID = -7086809764656937022L;
 
 @Column(length=128)
 private String title;
 
 @Lob
 private String description;
 
 @Column(length=512)
 private String link;
 
 @Column(length=64)
 private String author;
 
 @Column(length=40)
 private String guid;
 
 @ManyToOne
 @JoinColumn(name="feed_id", nullable=false)
 private Feed feed;
}