Skip to content

Commit 64a9dac

Browse files
committed
Merge branch 'message-bundle-feature' into main
2 parents f280c74 + f0e767e commit 64a9dac

26 files changed

+467
-153
lines changed

src/main/java/ir/bigz/springbootreal/commons/generallog/AppLogAspect.java

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
11
package ir.bigz.springbootreal.commons.generallog;
22

3-
import com.fasterxml.jackson.databind.ObjectMapper;
43
import ir.bigz.springbootreal.commons.util.Utils;
54
import ir.bigz.springbootreal.exception.AppException;
65
import ir.bigz.springbootreal.exception.HttpExceptionModel;
76
import org.aspectj.lang.JoinPoint;
8-
import org.aspectj.lang.Signature;
97
import org.aspectj.lang.annotation.*;
108
import org.slf4j.Logger;
119
import org.slf4j.LoggerFactory;
12-
import org.springframework.beans.factory.annotation.Autowired;
1310
import org.springframework.http.ResponseEntity;
1411
import org.springframework.stereotype.Component;
15-
import org.springframework.web.context.request.RequestContextHolder;
16-
import org.springframework.web.context.request.ServletRequestAttributes;
1712

1813
import javax.servlet.http.HttpServletRequest;
1914
import java.util.Arrays;
@@ -56,15 +51,15 @@ public void afterReturningResponseOfControllerMethod(JoinPoint joinPoint, Object
5651
public void logAfterThrowException(JoinPoint joinPoint, AppException exception){
5752
String methodName = joinPoint.getSignature().getName();
5853
LOG.info("exception method: {} | errorCode: {} | message: {}",
59-
methodName, exception.getHttpErrorCode(), exception.getDetail());
54+
methodName, exception.getSampleExceptionType().getErrorCode(), exception.getDetail());
6055
}
6156

62-
@AfterReturning(value = "execution(* ir.bigz.springbootreal.exception.validation.ErrorController.*(..))", returning = "object")
57+
@AfterReturning(value = "@annotation(ir.bigz.springbootreal.validation.annotation.ValidationLogResponseHandled)", returning = "object")
6358
public void logAfterThrowValidationException(JoinPoint joinPoint, Object object){
6459
HttpExceptionModel httpExceptionModel = (HttpExceptionModel) ((ResponseEntity) object).getBody();
6560
LOG.info("validation exception path: {} | errorCode: {} | errors: {}",
6661
httpExceptionModel.getValidationError().getPath(),
67-
httpExceptionModel.getHttpErrorCode(),
62+
httpExceptionModel.getErrorCode(),
6863
httpExceptionModel.getValidationError().getErrors());
6964
}
7065
}

src/main/java/ir/bigz/springbootreal/commons/util/Utils.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import ir.bigz.springbootreal.dto.SqlOperation;
55
import ir.bigz.springbootreal.dto.ValueCondition;
66
import ir.bigz.springbootreal.exception.AppException;
7-
import ir.bigz.springbootreal.exception.HttpErrorCode;
7+
import ir.bigz.springbootreal.exception.SampleExceptionType;
88
import org.javatuples.Quartet;
99
import org.springframework.data.domain.Sort;
1010

@@ -53,7 +53,7 @@ public static boolean isNotNull(String s) {
5353
}
5454

5555
public static boolean isNull(String s) {
56-
return s == null || s.equals("") || s.toLowerCase().equals("null");
56+
return s == null || s.equals("") || s.equalsIgnoreCase("null");
5757
}
5858

5959
public static boolean isNotNull(Object obj) {
@@ -121,7 +121,7 @@ public static List<Sort.Order> getSortOrderFromPagedQuery(PagedQuery pagedQuery,
121121
orders.add(order);
122122
}catch (Exception e){
123123
throw AppException.newInstance(
124-
HttpErrorCode.ERR_10705, String.format("field %s ordering is wrong", orderParam)
124+
SampleExceptionType.CREATE_QUERY_ERROR, String.format("field %s ordering is wrong", orderParam)
125125
);
126126
}
127127
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package ir.bigz.springbootreal.configuration;
2+
3+
import org.springframework.beans.factory.annotation.Value;
4+
import org.springframework.context.MessageSource;
5+
import org.springframework.context.annotation.Bean;
6+
import org.springframework.context.annotation.Configuration;
7+
import org.springframework.context.annotation.Primary;
8+
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
9+
import org.springframework.context.support.ResourceBundleMessageSource;
10+
import org.springframework.web.servlet.LocaleResolver;
11+
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
12+
13+
import java.util.Locale;
14+
import java.util.Objects;
15+
16+
/**
17+
* you can define bean for message resource that it's read from specific path and inject bean in every class you want
18+
* or use default messageResource bean that read from spring config define in application.properties file
19+
*/
20+
21+
@Configuration
22+
public class LocaleConfig {
23+
24+
@Value("${spring.messages.basename}")
25+
private String basename;
26+
27+
@Value("${spring.messages.encoding}")
28+
private String encoding;
29+
30+
@Bean
31+
public LocaleResolver localeResolver() {
32+
AcceptHeaderLocaleResolver localResolver = new AcceptHeaderLocaleResolver();
33+
localResolver.setDefaultLocale(Locale.US);
34+
return localResolver;
35+
}
36+
37+
@Bean("loadErrorMessageSource")
38+
public ReloadableResourceBundleMessageSource errorCodeSourceDesc(){
39+
return loadMessageSource("classpath:lang/error/code", 20, null);
40+
}
41+
42+
public ReloadableResourceBundleMessageSource loadMessageSource(String path, Integer timeToCache, String defaultEncoding){
43+
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
44+
messageSource.setBasename(path);
45+
messageSource.setDefaultEncoding(Objects.isNull(defaultEncoding) ? encoding: defaultEncoding);
46+
messageSource.setCacheSeconds(Objects.isNull(timeToCache) ? 10 : timeToCache);
47+
return messageSource;
48+
}
49+
50+
@Bean
51+
@Primary
52+
public MessageSource messageSource() {
53+
final ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
54+
messageSource.setBasename(basename);
55+
messageSource.setDefaultEncoding(encoding);
56+
return messageSource;
57+
}
58+
}
Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
package ir.bigz.springbootreal.controller;
22

3+
import ir.bigz.springbootreal.commons.util.Utils;
34
import ir.bigz.springbootreal.dto.PagedQuery;
5+
import ir.bigz.springbootreal.exception.ExceptionType;
6+
import ir.bigz.springbootreal.exception.HttpExceptionModel;
7+
import ir.bigz.springbootreal.messages.MessageContainer;
8+
import org.springframework.context.MessageSource;
9+
import org.springframework.http.HttpStatus;
10+
import org.springframework.http.MediaType;
11+
import org.springframework.http.ResponseEntity;
412
import org.springframework.web.context.request.RequestContextHolder;
513
import org.springframework.web.context.request.ServletRequestAttributes;
614

715
import javax.servlet.http.HttpServletRequest;
8-
import java.util.HashMap;
9-
import java.util.Map;
16+
import java.util.*;
1017
import java.util.stream.Collectors;
1118

1219
public abstract class AbstractController {
@@ -17,22 +24,20 @@ protected HttpServletRequest request() {
1724

1825
protected PagedQuery getPagedQuery() {
1926
return new PagedQuery(request().getParameterMap().entrySet().stream()
20-
.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()[0])));
27+
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue()[0])));
2128
}
2229

2330
protected PagedQuery getPagedQuery(Map<String, String> extraParams) {
2431
var params = request().getParameterMap().entrySet().stream()
25-
.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()[0]));
32+
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue()[0]));
2633
if (extraParams != null)
2734
params.putAll(extraParams);
2835
return new PagedQuery(params);
2936
}
3037

3138
protected Map<String, String> getQueryString() {
32-
Map<String, String> result = new HashMap<>();
33-
result.putAll(request().getParameterMap().entrySet().stream()
34-
.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()[0])));
35-
return result;
39+
return new HashMap<>(request().getParameterMap().entrySet().stream()
40+
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue()[0])));
3641
}
3742

3843
protected Map<String, String> getUnlimitedSizeParam() {
@@ -42,4 +47,26 @@ protected Map<String, String> getUnlimitedSizeParam() {
4247
}
4348
};
4449
}
50+
51+
protected ResponseEntity<?> getSuccessMessage(MessageSource messageSource, MessageContainer messageContainer, Locale locale) {
52+
return ResponseEntity.status(HttpStatus.OK)
53+
.headers(httpHeaders -> httpHeaders.set("Content-Type", MediaType.APPLICATION_JSON_VALUE + "; charset=utf-8"))
54+
.body(messageSource.getMessage(messageContainer.getMessages().get(0).getMessageKey(),
55+
messageContainer.getMessages().get(0).getMessageParams(), Objects.nonNull(locale) ? locale : Locale.getDefault()));
56+
}
57+
58+
protected ResponseEntity<?> getErrorMessage(MessageSource messageSource, ExceptionType exceptionType, Locale locale, Object[] messageParams) {
59+
return ResponseEntity.status(exceptionType.getHttpStatus())
60+
.headers(httpHeaders -> httpHeaders.set("Content-Type", MediaType.APPLICATION_JSON_VALUE + "; charset=utf-8"))
61+
.body(getErrorModelResponse(exceptionType, messageSource, locale, messageParams));
62+
}
63+
64+
private HttpExceptionModel getErrorModelResponse(ExceptionType exceptionType, MessageSource messageSource, Locale locale, Object... messageParams) {
65+
return HttpExceptionModel.builder()
66+
.uuid(UUID.randomUUID().toString())
67+
.errorCode(exceptionType.getErrorCode())
68+
.message(messageSource.getMessage(exceptionType.getReasonMessage(), messageParams, Objects.nonNull(locale) ? locale : Locale.getDefault()))
69+
.timestamp(Utils.getTimestampNow().toString())
70+
.build();
71+
}
4572
}

src/main/java/ir/bigz/springbootreal/controller/SampleController.java

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
package ir.bigz.springbootreal.controller;
22

33
import ir.bigz.springbootreal.dto.PageResult;
4+
import ir.bigz.springbootreal.exception.SampleExceptionType;
5+
import ir.bigz.springbootreal.messages.MessageContainer;
6+
import ir.bigz.springbootreal.service.MessageService;
47
import ir.bigz.springbootreal.service.UserService;
58
import ir.bigz.springbootreal.viewmodel.UserModel;
69
import ir.bigz.springbootreal.viewmodel.search.UserSearchDto;
10+
import org.springframework.beans.factory.annotation.Autowired;
11+
import org.springframework.beans.factory.annotation.Qualifier;
12+
import org.springframework.context.MessageSource;
13+
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
714
import org.springframework.data.domain.Page;
815
import org.springframework.data.domain.Sort;
916
import org.springframework.http.HttpStatus;
@@ -13,19 +20,47 @@
1320

1421
import javax.validation.Valid;
1522
import java.util.List;
23+
import java.util.Locale;
1624

1725
@RestController
1826
@CrossOrigin
1927
@RequestMapping("/api")
20-
public class SampleController extends AbstractController{
28+
public class SampleController extends AbstractController {
2129

22-
final
23-
UserService userService;
30+
final UserService userService;
2431

25-
public SampleController(UserService userService) {
32+
final MessageService messageService;
33+
34+
final MessageSource source;
35+
36+
@Autowired
37+
@Qualifier("loadErrorMessageSource")
38+
ReloadableResourceBundleMessageSource loadMessageSource;
39+
40+
public SampleController(UserService userService, MessageService messageService, MessageSource source) {
2641
this.userService = userService;
42+
this.messageService = messageService;
43+
this.source = source;
44+
}
45+
46+
@GetMapping("/v1/geterror")
47+
public ResponseEntity<?> getErrorMessage(
48+
@RequestHeader(name = "Accept-Language", required = false) final Locale locale) {
49+
MessageContainer messageContainer = messageService.getErrorMessage("internal_error");
50+
return getErrorMessage(loadMessageSource,
51+
SampleExceptionType.of(messageContainer.getErrorMessages().get(0).getMessageKey()),
52+
locale, messageContainer.getErrorMessages().get(0).getMessageParams());
53+
}
54+
55+
@GetMapping("/v1/welcome")
56+
public ResponseEntity<?> getLocaleMessage(
57+
@RequestHeader(name = "Accept-Language", required = false) final Locale locale,
58+
@RequestParam(name = "username", defaultValue = "Java Geek", required = false) final String username) {
59+
MessageContainer messageContainer = messageService.getNormalMessage("welcome.message", username);
60+
return getSuccessMessage(source, messageContainer, locale);
2761
}
2862

63+
2964
@GetMapping(path = "/v1/user/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
3065
@ResponseStatus(HttpStatus.OK)
3166
public ResponseEntity<?> getUserById(@PathVariable("id") long id) {
@@ -52,7 +87,7 @@ public ResponseEntity<?> updateUser(@RequestBody UserModel userModel, @PathVaria
5287
@ResponseStatus(HttpStatus.ACCEPTED)
5388
public ResponseEntity<?> deleteUser(@PathVariable("id") long userId) {
5489
String result = userService.deleteUser(userId);
55-
if(result.equals("Success")){
90+
if (result.equals("Success")) {
5691
return ResponseEntity.ok(result);
5792
}
5893
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(result);

src/main/java/ir/bigz/springbootreal/dal/DaoRepositoryImpl.java

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import ir.bigz.springbootreal.dto.PageResult;
44
import ir.bigz.springbootreal.dto.PagedQuery;
55
import ir.bigz.springbootreal.exception.AppException;
6-
import ir.bigz.springbootreal.exception.HttpErrorCode;
6+
import ir.bigz.springbootreal.exception.SampleExceptionType;
77
import org.hibernate.Session;
88
import org.hibernate.jpa.QueryHints;
99
import org.springframework.data.domain.Page;
@@ -37,7 +37,7 @@ public abstract class DaoRepositoryImpl<T, K extends Serializable> implements Da
3737

3838
protected CriteriaBuilder criteriaBuilder;
3939

40-
private static int maxPageSize = 1000;
40+
private static final int maxPageSize = 1000;
4141

4242
@SuppressWarnings("unchecked")
4343
protected DaoRepositoryImpl() {
@@ -100,7 +100,7 @@ public <S extends T> void delete(S entity) {
100100
@Override
101101
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
102102
public void deleteById(K id) {
103-
entityManager.remove(findById(id).get());
103+
findById(id).ifPresent(t -> entityManager.remove(t));
104104
}
105105

106106
@Override
@@ -170,10 +170,10 @@ public PageResult<T> pageCreateQuery(String nativeQuery, PagedQuery pagedQuery,
170170
if (orderField.length > 1 && orderField[1].equalsIgnoreCase(PagedQuery.ORDER_DESC)) {
171171
order = PagedQuery.ORDER_DESC;
172172
}
173-
orderString.append(orderColumn + " " + order);
173+
orderString.append(orderColumn).append(" ").append(order);
174174
}catch (Exception e){
175175
throw AppException.newInstance(
176-
HttpErrorCode.ERR_10705, String.format("field %s ordering is wrong", orderParam)
176+
SampleExceptionType.CREATE_QUERY_ERROR, String.format("field %s ordering is wrong", orderParam)
177177
);
178178
}
179179
}
@@ -323,13 +323,10 @@ protected Long totalCountOfSearch(String queryString, Map<String, Object> parame
323323
protected List<Order> orderByClauseBuilder(Root<T> root, Sort sort){
324324

325325
List<Order> orders = new ArrayList<>();
326-
Iterator<Sort.Order> iterator = sort.iterator();
327-
while(iterator.hasNext()){
328-
Sort.Order order = iterator.next();
329-
if(order.getDirection() == Sort.Direction.ASC){
326+
for (Sort.Order order : sort) {
327+
if (order.getDirection() == Sort.Direction.ASC) {
330328
orders.add(criteriaBuilder.asc(root.get(order.getProperty())));
331-
}
332-
else{
329+
} else {
333330
orders.add(criteriaBuilder.desc(root.get(order.getProperty())));
334331
}
335332
}

src/main/java/ir/bigz/springbootreal/exception/AppException.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
public class AppException extends ResponseStatusException{
77

8-
private HttpErrorCode httpErrorCode;
9-
private String detail;
8+
private final SampleExceptionType sampleExceptionType;
9+
private final String detail;
1010

1111

1212
static public AppException newInstance(HttpStatus status) {
@@ -21,27 +21,27 @@ static public AppException newInstance(HttpStatus status, String message, Throwa
2121
return new AppException(status, message, cause, null, null);
2222
}
2323

24-
static public AppException newInstance(HttpStatus status, String message, Throwable cause, HttpErrorCode errorCode) {
25-
return new AppException(status, message, cause, errorCode, null);
24+
static public AppException newInstance(HttpStatus status, String message, Throwable cause, SampleExceptionType exceptionType) {
25+
return new AppException(status, message, cause, exceptionType, null);
2626
}
2727

28-
static public AppException newInstance(HttpErrorCode errorCode, String message, Throwable cause) {
29-
return new AppException(errorCode.getStatus(), message, cause, errorCode, null);
28+
static public AppException newInstance(SampleExceptionType exceptionType, String message, Throwable cause) {
29+
return new AppException(exceptionType.getHttpStatus(), message, cause, exceptionType, null);
3030
}
3131

32-
static public AppException newInstance(HttpErrorCode errorCode, String detail) {
33-
return new AppException(errorCode.getStatus(), null, null, errorCode, detail);
32+
static public AppException newInstance(SampleExceptionType exceptionType, String detail) {
33+
return new AppException(exceptionType.getHttpStatus(), null, null, exceptionType, detail);
3434
}
3535

3636

37-
public AppException(HttpStatus httpStatus, String message, Throwable cause, HttpErrorCode errorCode, String detail){
37+
public AppException(HttpStatus httpStatus, String message, Throwable cause, SampleExceptionType exceptionType, String detail){
3838
super(httpStatus, message, cause);
39-
this.httpErrorCode = errorCode;
39+
this.sampleExceptionType = exceptionType;
4040
this.detail = detail;
4141
}
4242

43-
public HttpErrorCode getHttpErrorCode() {
44-
return httpErrorCode;
43+
public SampleExceptionType getSampleExceptionType() {
44+
return sampleExceptionType;
4545
}
4646

4747
public String getDetail() {

0 commit comments

Comments
 (0)