spring boot redis boolean value is not working - java

I am trying to get data from redis using crudRepository but it is not filtering by the boolean field. When I write repository.findAll() i am getting a list of objects and this object list's elements has a false field as I saved. But if I write a query for filtering just 'false' ones, it is returning only an empty array. Here is my code:
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
#RedisHash("StateData")
public class StateDataCache implements Serializable {
#Id String id;
private String deviceId;
private String topic;
private String message;
private String lat;
private String lon;
private boolean isActive;
}
#Repository
public interface StateDataCacheRepository extends CrudRepository<StateDataCache, String> {
List<StateDataCache> findAllByActiveFalseAndDeviceId(String deviceId);
List<StateDataCache> findAllByActiveIs(boolean sent);
List<StateDataCache> findAllByActiveFalse();
}
#Configuration
#EnableRedisRepositories
public class RedisConfig {
#Value("${spring.data.redis.host}")
private String redisHost;
#Value("${spring.data.redis.port}")
private int redisPort;
#Bean
public LettuceConnectionFactory redisStandAloneConnectionFactory() {
return new LettuceConnectionFactory(new RedisStandaloneConfiguration(redisHost, redisPort));
}
#Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisStandAloneConnectionFactory());
return template;
}
}

Related

Cloudinary image upload not persisting image and returning null value in spring boot app

I'm working on a spring boot ecommerce app that requires cloudinary to persist image and get using the url.
However, all effort to get this done has been proved abortive. The code is not throwing any error but its not persisting in the cloudinary page and the database. And the response is null.
This is a response for example. Meanwhile i expect a link in the form of String
{
"productName": "Track suit",
"price": 300,
"productDescription": "XXL",
"productImage1": "",
"productImage2": "",
"productImage3": ""
}
This is my code
ENTITY
#Entity
public class Product {
#Id
#GeneratedValue(generator="system-uuid")
#GenericGenerator(name="system-uuid", strategy = "uuid")
private String id;
#Column
private String productName;
#Column
private double price;
#Column
private String productDescription;
#Column(nullable = false)
private String productImage1;
#Column(nullable = true)
private String productImage2;
#Column(nullable = true)
private String productImage3;
private LocalDateTime createdDate;
private LocalDateTime updatedDate;
#ManyToOne
#JoinColumn(name = "admin_id")
private Admin admin;
#ManyToOne
#JoinColumn(name = "category_id")
private Category category;
#ManyToOne
#JoinColumn(name = "users_entity_id")
private UsersEntity usersEntity;
}
REQUEST DTO
#Data
public class UploadProductRequestDto {
private String productName;
private double price;
private String productDescription;
private MultipartFile productImage1;
private MultipartFile productImage2;
private MultipartFile productImage3;
}
RESPONSE DTO
#Data
public class UploadProductResponseDto {
private String productName;
private double price;
private String productDescription;
private String productImage1;
private String productImage2;
private String productImage3;
}
REPOSITORY
public interface ProductRepository extends JpaRepository<Product,String> {
Optional<Product> findByProductName(String productName);
}
SERVICE
public interface ProductService {
UploadProductResponseDto uploadProducts(UploadProductRequestDto uploadProductRequestDto, String categoryName) throws AuthorizationException, GeneralServiceException, ImageUploadException;
}
SERVICEIMPL
#Slf4j
#Service
public class ProductServiceImpl implements ProductService {
#Autowired
CloudStorageService cloudStorageService;
#Autowired
AdminRepository adminRepository;
#Autowired
CategoryRepository categoryRepository;
#Autowired
PasswordEncoder passwordEncoder;
#Autowired
ModelMapper modelMapper;
#Autowired
UserPrincipalService userPrincipalService;
#Autowired
UserRepository userRepository;
#Autowired
ProductRepository productRepository;
#Override
public UploadProductResponseDto uploadProducts(UploadProductRequestDto uploadProductRequestDto, StringcategoryName) throws AuthorizationException, GeneralServiceException, ImageUploadException {
Optional<Category> checkCategory = categoryRepository.findByCategoryName(categoryName);
if (checkCategory.isEmpty()){
throw new AuthorizationException(CATEGORY_NOT_RECOGNIZED);
}
Product product = new Product();
product=mapAdminRequestDtoToProduct(uploadProductRequestDto,product);
productRepository.save(product);
UploadProductResponseDto adminUploadProductResponseDto = packageAdminProductUploadResponseDTO(product);
return adminUploadProductResponseDto;
}
private UploadProductResponseDto packageAdminProductUploadResponseDTO(Product product){
UploadProductResponseDto uploadProductResponseDto=new UploadProductResponseDto();
modelMapper.map(product,uploadProductResponseDto);
return uploadProductResponseDto;
}
private Product mapAdminRequestDtoToProduct(UploadProductRequestDto uploadProductRequestDto,Product product) throws ImageUploadException {
modelMapper.map(uploadProductRequestDto,product);
product=uploadProductImagesToCloudinaryAndSaveUrl(uploadProductRequestDto,product);
product.setId("Product "+ IdGenerator.generateId());
return product;
}
private Product uploadProductImagesToCloudinaryAndSaveUrl(UploadProductRequestDto uploadProductRequestDto,Product product) throws ImageUploadException {
product.setProductImage1(imageUrlFromCloudinary(uploadProductRequestDto.getProductImage1()));
product.setProductImage2(imageUrlFromCloudinary(uploadProductRequestDto.getProductImage2()));
product.setProductImage3(imageUrlFromCloudinary(uploadProductRequestDto.getProductImage3()));
return product;
}
private String imageUrlFromCloudinary(MultipartFile image) throws ImageUploadException {
String imageUrl="";
if(image!=null && !image.isEmpty()){
Map<Object,Object> params=new HashMap<>();
params.put("public_id","E&L/"+extractFileName(image.getName()));
params.put("overwrite",true);
try{
Map<?,?> uploadResult = cloudStorageService.uploadImage(image,params);
imageUrl= String.valueOf(uploadResult.get("url"));
}catch (IOException e){
e.printStackTrace();
throw new ImageUploadException("Error uploading images,vehicle upload failed");
}
}
return imageUrl;
}
private String extractFileName(String fileName){
return fileName.split("\\.")[0];
}
}
Controller
#Slf4j
#RestController
#RequestMapping(ApiRoutes.ENMASSE)
public class ProductController {
#Autowired
ProductService productService;
#PostMapping("/upload-product/categoryName")
public ResponseEntity<?> UploadProduct(#ModelAttribute UploadProductRequestDto UploadProductRequestDto,#RequestParam String categoryName){
try{
return new ResponseEntity<>
(productService.uploadProducts(UploadProductRequestDto,categoryName), HttpStatus.OK);
}catch (Exception exception){
return new ResponseEntity<>(exception.getMessage(),HttpStatus.BAD_REQUEST);
}
}
}
CLOUD
cloudConfig
#Component
#Data
public class CloudinaryConfig {
#Value("${CLOUD_NAME}")
private String cloudName;
#Value("${API_KEY}")
private String apikey;
#Value("${API_SECRET}")
private String secretKey;
}
CloudConfiguration
#Component
public class CloudinaryConfiguration {
#Autowired
CloudinaryConfig cloudinaryConfig;
#Bean
public Cloudinary getCloudinaryConfig(){
return new Cloudinary(ObjectUtils.asMap("cloud_name",cloudinaryConfig.getCloudName(),
"api_key",cloudinaryConfig.getApikey(),"api_secret",cloudinaryConfig.getSecretKey()));
}
}
CloudinaryStorageServiceImpl
#Service
public class CloudinaryStorageServiceImpl implements CloudStorageService{
#Autowired
Cloudinary cloudinary;
#Override
public Map<?, ?> uploadImage(File file, Map<?, ?> imageProperties) throws IOException {
return cloudinary.uploader().upload(file,imageProperties);
}
#Override
public Map<?, ?> uploadImage(MultipartFile multipartFile, Map<?, ?> imageProperties) throws IOException {
return cloudinary.uploader().upload(multipartFile.getBytes(),imageProperties);
}
}
CloudStorageService
public interface CloudStorageService {
Map<?,?> uploadImage(File file, Map<?,?> imageProperties) throws IOException;
Map<?,?> uploadImage(MultipartFile multipartFile, Map<?, ?> imageProperties) throws IOException;
}
You didn't include the implementation of cloudStorageService.uploadImage(?,?) in the code you pasted here.
Cloudinary's Java implementation requires you pass in the multipart file in bytes. I do not know if you have that since your upload method isn't here.
Maybe refer to the simple implementation here
PS: You can clone the repo to see the implementation of the upload method in the CloudinaryServiceImpl.
It happens that there is nothing wrong with my code. The issue is that it has to be coupled with the frontend so the image tag can render it. Thank you.

Why Spring Data ensureIndex.expire does not work with ReactiveMongoTemplate

I have a Spring-Boot application and MongoDB as database.
I have an entity:
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
#Document(COLLECTION_NAME)
public class PersonEntity {
public static final String COLLECTION_NAME = "person_info";
private static final String PERSON_NAME = "person_name";
private static final String CREATED_AT = "created_at";
#Id
private PersonId id;
#Field(name = PERSON_NAME)
private String personName;
#Field(name = CREATED_AT)
private LocalDateTime createdAt;
}
I have a repository:
#Slf4j
#Repository
public class PersonRepositoryImpl implements PersonRepository {
private final int expireAfterSeconds;
private final ReactiveMongoTemplate mongoTemplate;
public SellerRequestInfoCustomRepositoryImpl(#Value("${ttl.index}") int expireAfterSeconds, ReactiveMongoTemplate mongoTemplate) {
this.expireAfterSeconds = expireAfterSeconds;
this.mongoTemplate = mongoTemplate;
}
#Override
public void saveWithTtl(PersonEntity entity) {
mongoTemplate.indexOps(PersonEntity.COLLECTION_NAME)
.ensureIndex(new Index().on(PersonEntity.CREATED_AT, ASC)
.expire(expireAfterSeconds));
mongoTemplate.save(entity).subscribe(result -> log.info("Entity has been saved: {}", result));
}
}
And I have an application.yml:
...
data:
mongodb:
auto-index-creation: true
...
ttl:
index: 20
But, when I save the entity from component like:
sellerRequestInfoCustomRepository.saveWithTtl(entity);
The document is been creating in mongodb, but the ttl index NOT:
screenshot
What am I doing wrong?

RedisTemplate use GenericFastJsonRedisSerializer can't deserialize parent class attributes

First of all, I create a parent class implements Serializable, then create a child class to extends it. And I use RedisTemplate with GenericFastJsonRedisSerializer config to put data into redis, but when I get it back from Reids, the data is changed.Please tell me why and how to fix it?
#Data
public class People implements Serializable {
public Long id;
public String name;
}
#EqualsAndHashCode(callSuper = true)
#Data
public class Student extends People{
private String sName;
}
#Bean(name = "redisTemplate")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(factory);
RedisSerializer keySerializer = new StringRedisSerializer();
RedisSerializer valueSerializer = new GenericFastJsonRedisSerializer();
redisTemplate.setDefaultSerializer(valueSerializer);
redisTemplate.setKeySerializer(keySerializer);
redisTemplate.setValueSerializer(valueSerializer);
redisTemplate.setHashKeySerializer(keySerializer);
redisTemplate.setHashValueSerializer(valueSerializer);
RedisUtil.init(redisTemplate);
return redisTemplate;
}
#Autowired
private RedisTemplate<String, Object> redisTemplate;
#Test
public void cacheDeserialize(){
Student student = new Student();
student.setId(11111111111111111L);
student.setName("parent name");
student.setSName("child name");
redisTemplate.opsForValue().set("parent-child-test", student);
Object value = redisTemplate.opsForValue().get("parent-child-test");
System.out.println(value); // print:Student(sName=child name), but I wish it print Student(id=111111111,name=parent name,sName=child name)
}
But:
Test result image
Solution one: use Lombok.annotation #ToString(callSuper = true) in chile class;
Solution two: take parent class attrs to child class;
You need to implement both classes with Serializable and define serialVersionUID like this
public class People implements Serializable {
private static final long serialVersionUID = 7156526077883281623L;
}

Can't bind properties with #Bean and #ConfigurationProperties

I am reading configuration from properties file. Now I am having an error that I think is related to sequence of initialization of spring bean.
If I do private Map name = new HashMap<>(); It can be successfully load from properties file.
But now I am having Could not bind properties to ServiceNameConfig
I don't know why this happen and how to deal with it.
#ConfigurationProperties(prefix = "amazon.service")
#Configuration
#EnableConfigurationProperties(ServiceNameConfig.class)
public class ServiceNameConfig {
//If I do private Map<String, String> name = new HashMap<>(); It can be successfully load from properties file.
private Map<String, String> name;
#Bean(value = "serviceName")
public Map<String, String> getName() {
return name;
}
public void setName(Map<String, String> name) {
this.name = name;
}
}
its usage;
#Autowired
#Qualifier("serviceName")
Map<String, String> serviceNameMap;
You can replace your config class to be like this (simpler);
#Configuration
public class Config {
#Bean
#ConfigurationProperties(prefix = "amazon.service")
public Map<String, String> serviceName() {
return new HashMap<>();
}
}
For #ConfigurationProperties injection, you'd need to supply an empty instance of the bean object. Check more about it on baeldung
Or an alternative way, you can use a pojo class to handle the configuration. For example;
You have properties like;
amazon:
service:
valueA: 1
valueB: 2
details:
valueC: 3
valueD: 10
and you can use a pojo like the following;
class Pojo {
private Integer valueA;
private Integer valueB;
private Pojo2 details;
// getter,setters
public static class Pojo2 {
private Integer valueC;
private Integer valueD;
// getter,setters
}
}
and use it in the config class like;
#Configuration
public class Config {
#Bean
#ConfigurationProperties(prefix = "amazon.service")
public Pojo serviceName() {
return new Pojo();
}
}

java.lang.StackOverflowError: null for the jpa saveAll

I am getting these error while integrating the spring-boot with JPA repository
here is the code
#CrossOrigin(origins = "http://localhost:4200")
#RestController
#RequestMapping("/api")
public class EmpController {
#Autowired
private CrudRepo crud;
#Autowired
private AddrCrudRepo addr;
#Autowired
private EntityManager entity;
//#Autowired
//private ModelMapper mapper;
private static int count = 0;
#Bean
public ModelMapper model() {
return new ModelMapper();
}
//#Autowired
// public EmpController(ModelMapper mapper) {
// this.mapper = mapper;
// }
#RequestMapping(path = "/post-addr", method = RequestMethod.POST)
public List<AddressModel> postAddr(#Valid #RequestBody List<AddressRequest> addr1){
// crud.findById(id)
//AddressModel list = new AddressModel();
EmployeeModel emp = new EmployeeModel();
System.out.println("CALLING THE MAPPER "+addr1);
List<AddressModel> addr_list = ObjectMapperUtils.mapAll(addr1, AddressModel.class);
System.out.println("CALLED THE MAPPER "+addr_list);
addr_list.forEach((a) -> {
crud.findById(a.getEmpId()).ifPresent((b) -> {
System.out.println(this.count++);
a.setEmp_id(b);
b.getAddress().add(a);
});
});
// AddressModel addr_list = model().map(addr1, AddressModel.class);
//
// crud.findById(addr1.getEmp_id()).ifPresent((b) -> {
// addr_list.setEmp_id(b);
//
// });`enter code here`
System.out.println(addr_list.size());
List<AddressModel> addr3 = addr.saveAll(addr_list);
System.out.println(addr3);
return addr_list;
}
getting an error in the postAddr method as when it returns the List<AddressModel> and here is the AddressModel
#Entity
#Table(name="Emp_Address")
public class AddressModel implements Serializable{
#Column(name="address_id")
#Id
private Integer address_id;
#Column(name="city")
private String city;
#Column(name="states")
private String states;
#Transient
private Integer empId;
#ManyToOne
#JoinColumn(name="emp_id")
private EmployeeModel emp_id;
public AddressModel() {
}
//getter and setter
and EmployeeModel
#Entity
#Table(name="Employee")
public class EmployeeModel implements Serializable{
#Column(name="Emp_id")
#Id
private Integer emp_id;
#Column(name="Emp_Name")
private String emp_name;
#OneToMany(mappedBy="emp_id")
private Collection<AddressModel> address = new ArrayList<>();
public EmployeeModel() {
}
//getter and setters
so while saveAll is done properly but when the postAddr method returns the List it throws the StackOverflow
This StackOverflow error is coming because generated toString methods of both classes are circularly dependent on each other.
EmployeeModel tries to print AddressModel but again AddressModel tries to print EmployeeModel and hence the error.
Try removing AddressModel from toString method of EmployeeModel class or reverse, remove EmployeeModel from toString method of AddressModel class.

Categories