Spring UTF-8 replace chars "ě", "č", "ř" to "?" - spring

I have problems with UTF-8 encoding.
I have a Spring-Boot REST Server. When I perform a PUT request to save an article and there are special characters in the content (like "ě", "č" or "ř") they will be replace by "?" characters. But if I edit an article using phpmyadmin and perform a GET request it returns "ě", "č" and "ř" correctly.
package cz.flay.fellcms.http;
import cz.flay.fellcms.dao.ArticlesRepository;
import cz.flay.fellcms.entities.Article;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
#CrossOrigin
#RestController
#RequestMapping(path = "/api/articles", produces = "application/json;charset=UTF-8")
public class ArticleRestController {
#Autowired
private ArticlesRepository articlesRepository;
#CrossOrigin
#GetMapping(path = "/all")
public #ResponseBody Iterable<Article> getAll(){
return articlesRepository.getAll();
}
#CrossOrigin
#GetMapping(path = "/newest")
public #ResponseBody Iterable<Article> getNewest(){
return articlesRepository.getNewest();
}
#CrossOrigin
#PutMapping(path = "/save")
public #ResponseBody HttpStatus saveArticle(#RequestBody Article article) {
articlesRepository.save(article);
return HttpStatus.OK;
}
#CrossOrigin
#GetMapping(path = "/get")
public #ResponseBody Article getArticle(#RequestParam int id) {
return articlesRepository.findOne(id);
}
}
I tried to log an article out to the console. Then the special charactes are displayed correctly.
I tried a lot of things that I found in other discussions but nothing helped me.
Thanks for any help !

The way it worked for me was to enter the following in the mysql configuration file (my.cnf)
[mysql]
default-character-set=utf8
[mysqld]
character-set-server=utf8
The mysql configuration file is usually in /etc/mysql/my.cnf in linux (I tried it in Ubuntu 14.04). If it doesn't exist there you can create the file using sudo touch /etc/mysql/my.cnf; then edit the file.
Edit:
For Win Users: File is located in /mysql/bin/my.ini

Try this in your properties file;
spring.datasource.url = jdbc:mysql://localhost:3306/db_name?useUnicode=yes&characterEncoding=UTF-8

Related

Spring WebFlux FilePart transferTo method can't write file to dest path

import org.springframework.http.codec.multipart.FilePart;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import java.io.File;
#RestController
public class TestController {
#PostMapping("test")
public Mono<R> test(FilePart file){
String fileName = file.filename();
File newFile = new File("F:/images/banner/",fileName);
file.transferTo(newFile);
return Mono.just(R.ok());
}
}
i upload picture and use transferTo method to write file to the dest path.
but i can't found the picture in the F:/images/banner/
someone can help me? thanks
When writing reactive code you have to make sure it terminates, or in other words you need to subscribe to the publisher. The file.transferTo() returns a Mono<Void> which, if you don't subscribe, doesn't actually do anything.
What you can do in your case is the following, use the then method to return your result.
#PostMapping("test")
public Mono<R> test(FilePart file){
String fileName = file.filename();
File newFile = new File("F:/images/banner/",fileName);
return file.transferTo(newFile)
.then(Mono.just(R.ok()));
}
Now you return the call chain and the client will subscribe and things will start to happen. You could also add an additional onError call to return a error response when something breaks in the transfer.

Spring Boot: The image is not displayed in the browser, I have a 404 error

Hello everyone I'm learning spring boot and well I've been following some tutorials and well I'm stuck showing the image in the browser, I've already managed to save it in the path called "user-photos" but it doesn't save inside resources but as a separate folder, when I try to show it in the browser I get a 404 error.
This is my controller that I used to save an user with the image:
#PostMapping("/users/save")
public String saveUser(User user,
RedirectAttributes redirectAttributes,
#RequestParam("image")MultipartFile multipartFile) throws IOException {
if (!multipartFile.isEmpty()) {
String fileName = StringUtils.cleanPath(multipartFile.getOriginalFilename());
user.setPhotos(fileName);
User savedUser = userService.save(user);
String uploadDir = "ShopmeWebParent/ShopmeBackEnd/user-photos/" + savedUser.getId();
FileUploadUtil.saveFile(uploadDir, fileName, multipartFile);
}
// userService.save(user);
redirectAttributes.addFlashAttribute("message", "The user has been saved successfully.");
return "redirect:/users";
}
Now I created my MVC Controller to be allowed to show images called MvcConfig:
package com.shopme.admin;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.nio.file.Path;
import java.nio.file.Paths;
#Configuration
public class MvcConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String dirName = "user-photos";
Path userPhotosDir = Paths.get(dirName);
String userPhotosPath = userPhotosDir.toFile().getAbsolutePath();
registry.addResourceHandler("/user-photos/**")
.addResourceLocations("file:/" + userPhotosPath + "/");
}
}
Finally I created an img tag to show it with the followind code snippet:
<img th:if="${user.photos != null}" th:src="#{${user.photosImagePath}}" >
if you haven't solve it, you need to remove the in the controller "ShopmeWebParent/ShopmeBackEnd/" only leave the "user-photos + ..."

Getting 404 Not Found for basic spring rest api tutorial - 'hello world'

I am trying to create a rest api web application that can be eventually deployed into a container environment. I downloaded quite a few tutorials from spring.io to other websites as well but each time I use the exact repos I get a 404 error for the simple request.
To simplify it further I reduced it to 2 classes in one package:
project hierarchy
Main class:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
Controller Class:
#RestController
#RequestMapping("/")
public class RESTController {
private final AtomicLong counter = new AtomicLong();
private static final String template = "Hello, %s!";
/*
* REST API Test Methods
*/
#RequestMapping( "/greeting" )
public String greeting() {
return "It's working...!";
}
And of course the actual request:
http://localhost:8080/test_rest_api/greeting
HTTP Status 404 – Not Found
Type Status Report
Message /test_rest_api/greeting
Description The origin server did not find a current representation for the target resource or is not
willing to disclose that one exists.
Apache Tomcat/8.5.43
That is running on server by Run As - ; if I select Run as java application and select springboot the following error occurs:
java.lang.IllegalArgumentException: Sources must not be empty at
org.springframework.util.Assert.notEmpty(Assert.java:467)
I finally figured it out and it was a stupid mistake. I added the name of the project as part of the domain of the request url.
http://localhost:8080/test_rest_api/greeting
vs
http://localhost:8080/greeting

Redis SSL configuration is not clear in case of SpringBoot with lettuce-core

Spring-boot: 2.0.3.RELEASE
lettuce-core: 5.0.4.RELEASE
spring-data-redis: 2.0.8.RELEASE
So first of all my issue is solved I just don't understand why and it bothers me, so some clarification around this is appreciated.
I have this Redis Configuration in one of the micro-service I'm working on:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.resource.ClientResources;
import io.lettuce.core.resource.DefaultClientResources;
#Configuration
public class LettuceConfig {
#Bean(destroyMethod = "shutdown")
ClientResources clientResources() {
return DefaultClientResources.create();
}
#Bean(destroyMethod = "shutdown")
RedisClient redisClient(ClientResources clientResources) {
String host = System.getenv("spring_redis_host") != null ? System.getenv("spring_redis_host") : "127.0.0.1";
String port = System.getenv("spring_redis_port") != null ? System.getenv("spring_redis_port") : "6379";
String password = System.getenv("spring_redis_password") != null ? System.getenv("spring_redis_password") : "";
Boolean isLocal = host.equals("127.0.0.1");
RedisURI redisUri = RedisURI.Builder.redis(host).withSsl(!isLocal).withPassword(password).withPort(Integer.parseInt(port))
.build();
return RedisClient.create(clientResources, redisUri);
}
#Bean(destroyMethod = "close")
StatefulRedisConnection<String, String> connection(RedisClient redisClient) {
return redisClient.connect();
}
}
After I added actuator to the project I realized that the service couldn't connect to the remote Redis in AWS and the service throwed the following Exception:
java.io.IOException: Connection reset by peer
After a quick google search most of the answers suggested that the problem is around the SSL connection I have, but I was confused since the RedisURI contains the withSsl function call.
Just out of curiosity I added the following property to my application.properties file, since I'm using property based Redis configuration in the other services and I knew it works.
spring.redis.ssl=true
Now this solved my problem, but I don't understand why this approach is working and the RedisURI version is not.
Could somebody provide me an explanation, who has a clear understanding about the following situation please?
I can share more from the logs if needed. Thank you!

Spring Feign: Could not extract response: no suitable HttpMessageConverter found for response type

I am trying to get a Spring Cloud Netflix Feign client to fetch a bit of JSON over HTTP and convert it to an object. I keep getting this error instead:
org.springframework.web.client.RestClientException: Could not extract response: no suitable HttpMessageConverter found for response type [class io.urig.checkout.Book] and content type [application/json;charset=UTF-8]
Here's the bit of JSON returned from the remote service:
{
"id": 1,
"title": "Moby Dick",
"author": "Herman Melville"
}
Here's the corresponding class I'm trying to deserialize to:
package io.urig.checkout;
public class Book {
private long id;
private String title;
private String author;
public Book() {}
public Book(long id, String title, String author) {
super();
this.id = id;
this.title = title;
this.author = author;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
And here's my Feign client:
package io.urig.checkout;
import java.util.Optional;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import io.urig.checkout.Book;
#FeignClient(name="inventory", url="http://localhost:8080/")
public interface InventoryClient {
#RequestMapping(method = RequestMethod.GET, value = "books/{bookId}")
public Optional<Book> getBookById(#PathVariable(value="bookId") Long bookId);
}
What do I need to do to get this to work?
I don't know Feign, but when I've had "no suitable HttpMessageConverter found..." errors in the past, it's because the content type has not been registered. Perhaps you need to add this to the RequestMapping:
consumes = "application/json"
All I can suggest is to try to confirm if Feign configuration has MappingJackson2HttpMessageConverter registered as a converter for Book. Not sure if this is something that should work out of the box with Feign, or if you have to do it manually. I see an example on Feign's GitHub that has:
GitHub github = Feign.builder()
.encoder(new JacksonEncoder())
.decoder(new JacksonDecoder())
.target(GitHub.class, "https://api.github.com");
Have you created configuration using Feign.builder() or some equivalent configuration files?
You will need to ensure that you have at least one JSON library on your classpath. Feign supports both GSON and Jackson and Spring Cloud OpenFeign will autoconfigure the SpringEncoder and SpringDecoder instances with the appropriate MessageConverter if they are found on your classpath. Ensure that you have at least one of the following in your pom.xml or build.gradle
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.4</version>
</dependency>
or
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>
Once they are found, Spring will register the appropriate MessageConverter
I think your problem is the response type. Try converting it to Book from Optional. If you want to return an Optional than you should provide your custom converter.
Sorry, for too late answer.
Had the same problem.
Just add two parameters to your #RequestMapping -
consumes = "application/json", produces = "application/json"
In your code this will look like this -
package io.urig.checkout;
import java.util.Optional;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import io.urig.checkout.Book;
#FeignClient(name="inventory", url="http://localhost:8080/")
public interface InventoryClient {
#RequestMapping(method = RequestMethod.GET, value = "books/{bookId}", consumes = "application/json", produces = "application/json")
public Optional<Book> getBookById(#PathVariable(value="bookId") Long bookId);
}
Thanks to all who tried to help!
As it turned out my issue was a defective Maven dependency, probably corrupted during download or installation. Having entirely deleted the .m2/repository folder on my machine and then updating Maven dependencies for the project the issue is now gone.
I am late here but I would like to add one more point. In my case I observed Spring Feign client returns this exception when you specified the return type as a specific model/entity class and that entity is not found.
You should check the response for the another service which you are calling and see what response it returns in case the entity is not found, or in case an exception is thrown.
So in case an entity is not found or any exception is thrown and that response does not match to what you have specified in return type then this exception is thrown in the client service.

Resources