Spring MessageSource.getMessage with arguments containing International characters showing up as ISO-8859 encoded characters - spring-messaging

I am using Spring Message with placeholders to create an email message. The arguments for the placeholders contain International Characters. Once the email body text is set using the getMessage() method with message, arguments and Locale and email is sent, the email received has the placeholder values with ISO-8859 chars. How to ensure that the UTF-8 encoded Arguments are preserved while getting replaced in the message property.
Return property bundle:
#Bean
public MessageSource emailProps() {
ReloadableResourceBundleMessageSource messageSource = new
ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:props/Email");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
MailSender.java
#Autowired
private MessageSource emailProps;
public void send(String to, String language,String name, String org_name) throws MessagingException {
//org_name has values like "GmbH (Süd) München"
//some code here
MimeMessage message = javaMailSender.createMimeMessage();
MimeMessageHelper helper=new MimeMessageHelper(message,
MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED, "UTF-8");
//helper.setFrom, helper.setTo....
helper.setText(emailProps.getMessage("security.email.body", new Object[] {name,org_name},
Locale.GERMAN)+emailProps.getMessage("email.footer", null, Locale.GERMAN), true);
//remaining part of the code
}
In the Email org_name comes up as "GmbH (Süd) München".
Question: What should I do so that the UTF-8 encoded argument values are retained as-is? I have the argument values coming from DB and have verified that they do retain the encoding till the step before they are written into the message body.

Related

My SQSListener returns body as messageID, And How do I get send MessageId with QueueMessagingTemplate Spring Boot?

I have 2 issues regarding Spring AWS-SQS sdk, (Or maybe I am doing it wrong).
First is that I used CLI earlier and I managed to get the message Id of the sent message example:
aws sqs send-message --queue-url https://sqs.us-west-2.amazonaws.com/testqueue --message-body hooray
'{
"MD5OfMessageBody": "d3101ad",
"MessageId": "jdhj-933"
}
Now I tried with spring-cloud-starter-aws-messaging and I setup a Queue Messaging template like this
private final QueueMessagingTemplate queueMessagingTemplate;
public SqsQueueService(#Qualifier("amazonSQSAsync") final AmazonSQSAsync amazonSQS) {
this.queueMessagingTemplate = new QueueMessagingTemplate(amazonSQS);
}
public void sendMessage(String queueName, String queueMessage) {
Map<String, Object> headers = new HashMap<>();
queueMessagingTemplate.convertAndSend(queueName, queueMessage, headers);
}
I can seem to get the message Id of the sent message using queueMessagingTemplate.convertAndSend(queueName, queueMessage, headers);
I need the messageId to fulfil some business logic.
The second issue is my listener can receive messages however the messageID is null as well;
#Async
#SqsListener(value = "${notification.sqs-queue-url}", deletionPolicy = SqsMessageDeletionPolicy.NEVER)
public void listen(Acknowledgment acknowledgment, String message, String messageId) {
//messageId is equal to message here. which is wrong for me
}
The message is always equal to messageId, which is confusing, Any advice on where I maybe going wrong?
I changed the listner method signature to
#Async
#SqsListener(value = "${queue-url}", deletionPolicy = SqsMessageDeletionPolicy.NEVER)
public void listen(Acknowledgment acknowledgment, String message, #Headers MessageHeaders headers) throws ExecutionException, InterruptedException {
String messageId = (String) headers.get("MessageId");
acknowledgment.acknowledge().get();
}
Then extracted the messageId from the headers map

send mail through spring boot application

I am creating spring boot application where I have to send newly generated response string for each transaction to user as a text file attachment
so what will be the proper way to do this
any help would be appreciated
Try this below code:
#Override
public void sendMessageWithAttachment(
String to, String subject, String text, String pathToAttachment) {
// ...
MimeMessage message = emailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(text);
FileSystemResource file
= new FileSystemResource(new File(pathToAttachment));
helper.addAttachment("Invoice", file);
emailSender.send(message);
// ...
}

Spring MVC Test with Validation JSR-303/349: Locale or accept-language does not work in testing

I am working with Spring Framework 4.3.3
I have the following situation for a #Controller either for POST or PUT
For example for POST I have the following:
#PostMapping(value="/save",
consumes=MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces=MediaType.TEXT_HTML_VALUE)
public String saveOne(#Validated #ModelAttribute Persona persona,
BindingResult result,
RedirectAttributes redirectAttributes){
logger.info("saveOne: {}", persona.toString());
if(result.hasErrors()){
logger.error("# Errors: {}", result.getErrorCount());
logger.error("result: {}", result.toString());
return "persona/saveOne";
}
personaRestController.saveOne(persona);
redirectAttributes.addFlashAttribute("message", "process.successful");
return "redirect:/message";
}
The app works how is expected, through a Web Form this #PostMapping either saves/persists the data or validates the data and if it is invalid the same web form is shown with the error messages for each field and based about i18n such as English, Spanish and Portuguese. It related with JSR-439
About Java config infrastructure configuration I have the following:
#Bean
public LocaleChangeInterceptor localeChangeInterceptor(){
LocaleChangeInterceptor localeChangeInterceptor=new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("language");
//localeChangeInterceptor.setHttpMethods("post", "put");
return localeChangeInterceptor;
}
#Bean(name="localeResolver")
public LocaleResolver cookieLocaleResolver(){
CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver();
cookieLocaleResolver.setCookieName("language");
cookieLocaleResolver.setDefaultLocale(new Locale("en","US"));
return cookieLocaleResolver;
}
And
#EnableWebMvc
#Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
...
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptorConfig.localeChangeInterceptor());
}
The problem is about Spring MVC Test. I have the following:
#Before
public void setUp(){
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
...
#Test
public void saveOneHtmlPostInvalidMaxTest() throws Exception {
logger.info("saveOneHtmlPostInvalidMaxTest");
resultActions = mockMvc.perform(post(url)
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.locale(locale)
.header("accept-language", locale.toString())
.header("language", locale.toString())
.param("id", personaInvalidMax.getId())
.param("nombre", personaInvalidMax.getNombre())
.param("apellido", personaInvalidMax.getApellido())
....
.andDo(print());
Note observe:
.locale(locale)
.header("accept-language", locale.toString())
.header("language", locale.toString())
Even when some of them have no sense, they are there because I am trying to resolve the following situation:
The validation control from the server side works how is expected until some point.
First
I can confirm through .andDo(print()) method that MockHttpServletRequest prints
Headers = {Content-Type=[application/x-www-form-urlencoded],
accept-language=[pt_BR], language=[pt_BR]}
Observe pt_BR
Second
The #PostMapping that contains:
if(result.hasErrors()){
logger.error("# Errors: {}", result.getErrorCount());
logger.error("result: {}", result.toString());
return "persona/saveOne";
}
Prints...
7370 [Test worker] ERROR PersonaSaveOneController - result:
org.springframework.validation.BeanPropertyBindingResult: 4 errors
Field error in object 'persona' on field 'id': rejected value [0];
codes [Size.persona.id,Size.id,Size.java.lang.String,Size]; arguments
[org.springframework.context.support.DefaultMessageSourceResolvable:
codes [persona.id,id]; arguments []; default message [id],3,3];
default message [The size for the field must be between 3 and 3]
Observe the default message [id],3,3];
default message [The size for the field must be between 3 and 3]
Here two problems:
The locale or accept-language are ignored
The error messages prints always in English
What I need is that the error data prints for example in Portuguese and Spanish according the Locale sent. It should returns the error messages for each field in an expected language, in this case Portuguese
Again, it works when I use directly the Web Form, but not through the Test. I am assuming that exists an internal Spring component that works through production and has not been defined for Testing
Therefore, what is need it to accomplish this approach?
BTW: With the following (see I use classpath:), furthermore my .properties file are located in src/main/resources
#Bean(name="messageSource")
public ReloadableResourceBundleMessageSource reloadableResourceBundleMessageSource() {
ReloadableResourceBundleMessageSource resource = new ReloadableResourceBundleMessageSource();
resource.setBasenames(...
"classpath:/com/manuel/jordan/validation/validation");
resource.setDefaultEncoding("UTF-8");
return resource;
}
My #Test methods working around with Rest works fine about show and returning the error message according the Locale or accept-language defined (Access to MessageSource happens in the server side and works fine with the previous configuration). It just fails for non-Rest controllers

Encoding for downloaded files in Spring

I want to create a controller which will sent to client a CSV file, and I created the next controller:
#ResponseStatus(value = HttpStatus.OK)
#RequestMapping(value = "/csv", method = RequestMethod.GET)
public ResponseEntity downloadCsvAllInvoiceTransactionsByFilter(
#PageableDefault(direction = DESC, sort = "invoiceDate", size = 30) Pageable pageRequest) throws IOException {
String someVariable = "Some text";
byte[] out = someVariable.getBytes(Charset.forName("UTF-8"));
HttpHeaders responseHeaders = new HttpHeaders();
LOGGER.info(new String(out));
responseHeaders.add("content-disposition", "attachment; filename=transactions.csv" );
responseHeaders.add("Content-Type","text/csv; charset=utf-8");
return new ResponseEntity<>(out,responseHeaders,HttpStatus.OK);
}
Logger is displaying the correct string:
Some text
but in downloaded file there is another one
U29tZSB0ZXh0
How can I fix this?
Body of ResponseEntity goes through a message converter before it gets sent. The choice of the particular converter depends on class of the body and response and request headers.
I tried to reproduce the issue with your code snippet and got expected text in csv file. So I assume that you got a message converter registered that converts byte arrays the way you observe.
You can debug AbstractMessageConverterMethodProcessor#writeWithMessageConverters and see which converter is chosen and why.

Arabic is displayed as ????? in velocity template

Greetings all
i am using velocity templates in sending emails
and in the template i have some arabic texts
and when sending the email, the text appears like ??????????
i don't know why:
encoding is set to utf-8 before sending the email here:
VelocityEngineUtils.mergeTemplateIntoString(velocityEngine,templateName, "UTF-8",newModel);
i tried to add the charset in the vm, but with no luck:
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
any ideas why such problem occurs ?
I was able to produce Arabic text (تجاوز سعة مكدس) on a plain-text email sent from a Spring app. The text displayed properly on GMail as well as Thunderbird. Here's my mail sending logic:
public void send(String fromAddress, String fromName,
String toAddress, String subject,
String template, Map<String, Object> model) {
MimeMessagePreparator preparator = new MimeMessagePreparator() {
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper message = new MimeMessageHelper(
mimeMessage, "UTF-8");
message.setTo(toAddress);
message.setFrom(new InternetAddress(fromAddress, fromName));
message.setSubject(subject);
message.setText(VelocityEngineUtils
.mergeTemplateIntoString(velocityEngine, template, "UTF-8",
model));
}
};
mailSender.send(preparator);
}
Do you have any velocity.properties set? (particularly input.encoding or output.encoding) If not, try setting those both to UTF-8 also.

Resources