How to save image and Request body in to database using springBoot - spring

i am new to springBoot i am trying to save image and data in my local storage. its showing error like this Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type byte[] from String "\fakepath\book.jpg": Failed to decode VALUE_STRING as base64 (MIME-NO-LINEFEEDS): Illegal character ':' (code 0x3a) in base64 content; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type byte[] from String "\fakepath\book.jpg": Failed to decode VALUE_STRING as base64 (MIME-NO-LINEFEEDS): Illegal character ':' (code 0x3a) in base64 content at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 162] (through reference chain: com.msys.smartkart.entity.Product["image"])]
please help me to learning springboot thankyou in advance.
#Override
public void addProduct(Product product, MultipartFile multipartFile) throws IOException {
log.info("product details ");
log.info(String.valueOf(product));
byte[] image = multipartFile.getBytes();
log.info("adding image "+image);
Product product1 =new Product();
product1.setProductName(product.getProductName());
product1.setId(product.getId());
product1.setPrice(product.getPrice());
product1.setColor(product.getColor());
product1.setDescription(product.getDescription());
product1.setDetails(product.getDetails());
product1.setImage(image);
productRepository.save(product1);
log.info("saved product and its image");
}
#Entity
package com.msys.smartkart.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import javax.persistence.*;
import java.util.Date;
#Entity
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Product {
#Id
Integer id;
String productName;
String color;
String description;
String details;
Integer price;
#Lob
byte[] image;
#CreationTimestamp
Date date;
}

that question was already asked. you can find the question and solution here:
https://stackoverflow.com/a/39708658/19096791

Related

Handle Date data type with spring data ldap

I am using spring-data-ldap to find all the users who are created or modified in a certain date range. My UserRepository
package com.test.service.ldap.com;
import org.springframework.data.ldap.repository.LdapRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
#Repository
public interface UserRepository extends LdapRepository<User> {}
My User class
package com.test.service.ldap.com;
import lombok.Data;
import lombok.ToString;
import org.springframework.data.domain.Persistable;
import org.springframework.ldap.odm.annotations.Attribute;
import org.springframework.ldap.odm.annotations.Entry;
import org.springframework.ldap.odm.annotations.Id;
import org.springframework.ldap.odm.annotations.Transient;
import javax.naming.Name;
import java.util.Date;
#Entry(base = "ou=people,dc=example,dc=com",objectClasses = { "top","person","organizationalPerson","inetOrgPerson" })
#Data
#ToString
public final class User implements Persistable<Name> {
private #Id Name id;
private #Attribute(name = "cn") String firstname;
private #Attribute(name = "sn") String lastname;
private #Attribute(name = "mobile") String mobile;
private #Attribute(name = "createTimestamp") Date createdtime;
private #Attribute(name = "modifyTimestamp") Date modifiedtime;
#Transient
private Boolean isNew = false;
#Override
public boolean isNew() {
return isNew;
}
}
I get the below exception when I try to findAll()
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.util.Date] for value '20221229074251.850Z'
at org.springframework.core.convert.support.ObjectToObjectConverter.convert(ObjectToObjectConverter.java:117)
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:192)
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:175)
at org.springframework.ldap.odm.typeconversion.impl.ConversionServiceConverterManager.convert(ConversionServiceConverterManager.java:67)
...
...
I want to know
How to handle Date data type in spring-data-ldap
Can I use something like findAllOrderByModifiedTimeDesc or use Between two dates

How to fetch data from multiple tables and put into an custom object? spring boot?

JpaRepository
public interface SessionsStoreRepository extends JpaRepository<SessionsStore, Integer> {
SessionsStore findBySessionId(String sessionId);
//JPQL
#Query(value = "SELECT s.username,s.loginTime,s.logoutTime, e.firstName, e.lastName from SessionsStore s, Employee e "
+ " where e.username = s.username and s.isActive= 1")
List<ActiveSession> findUsers();
}
ActiveSession
import java.time.LocalDateTime;
import lombok.Data;
#Data
public class ActiveSession {
private String username;
private String firstName;
private String lastName;
private LocalDateTime loginTime;
private LocalDateTime logoutTime;
}
How can I store the data fetch by #Query(...) in ActiveSession Object Or is there any other way? I tried storing data into object (i.e List<Object>) but I'm using ftl for view and it does not allow you fetch the data unless the object have getters.
you can use a class-based projection to achive this.
More information here, or there is a good example of how to use it here

Problem Parsing request body of type json, containing a list of string to Flux of string in Spring reactive

I have a DTO as below:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import reactor.core.publisher.Flux;
#Data
#NoArgsConstructor
#AllArgsConstructor
public class InternetPackageDto {
private String id;
private String name;
private String termsAndConditions;
private String price;
private Flux<String> packageAttributes;
private Flux<String> extras;
}
And a Database Object as below:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import reactor.core.publisher.Flux;
#Document("internet_packages")
#Data
#NoArgsConstructor
#AllArgsConstructor
public class InternetPackage {
#Id
private String id;
private String name;
private String termsAndConditions;
private String price;
private Flux<StoreableAttribute> attributes;
private Flux<StoreableAttribute> extras;
}
The StorableAttribute Database Model like so:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
#Document("package_attributes")
#Data
#NoArgsConstructor
#AllArgsConstructor
public class StoreableAttribute {
#Id
private String id;
private String name;
private String description;
}
On the Data Object the fields: Flux<StoreableAttribute> attributes and Flux<StoreableAttribute> extras are stored in a separate collection alongside the Package Object. And is handled by the mapper as below:
public InternetPackage fromDto(InternetPackageDto dto) {
var internetPackage = new InternetPackage();
internetPackage.setName(dto.getName());
internetPackage.setPrice(dto.getPrice());
internetPackage.setId(dto.getId());
internetPackage.setExtras(this.resolePackageExtras(dto));
internetPackage.setAttributes(this.resolePackageAttributes(dto));
return internetPackage;
}
private Flux<StoreableAttribute> resolePackageExtras(InternetPackageDto dto) {
return this.storeableAttributeService.resolveAttributes(dto.getExtras());
}
for the extra and similarly for the attributes also.
And a simple controller method as below:
#PostMapping(produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
public Mono<InternetPackageDto> update(#RequestBody InternetPackageDto incomingPackageDto) {
return this.packageService
.updatePackage(this.dtoMapper.fromDto(incomingPackageDto))
.map(this.dtoMapper::toDto);
}
And when I make a post request I get an error stating
org.springframework.core.codec.CodecException: Type definition error: [simple type, class reactor.core.publisher.Flux]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `reactor.core.publisher.Flux` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
at [Source: (io.netty.buffer.ByteBufInputStream); line: 2, column: 13] (through reference chain: com.example.api.dto.InternetPackageDto["extras"])
Some more information:
I am using the class InternetPackageDto as a request object as well as a response object.
I am using Flux<String> and not List<String> since I wasn't sure if doing blocking resolution to list was a good idea.
The attributes are stored and managed separately.
And during the time of updating or inserting the package those; if a new extra or attribute is included the attributes collection in db will be updated with the insertion of new incoming extras and attributes.
It seems like I might have made a stupid mistake because I cannot find much information about this problem, or I am doing it completely wrong.
Any help would be greatly appreciated.
I think you should do smth like this
public Mono<InternetPackageDto> toDto(InternetPackage entity) {
var internetPackage = new InternetPackageDto();
internetPackage.setName(entity.getName());
internetPackage.setPrice(entity.getPrice());
internetPackage.setId(entity.getId());
return Mono.zip(Mono.just(internetPackage), entity.getExtras().collectList(), entity.getAttributes().collectList())
.flatMap(tu->{
var dto = tu.getT1();
dto.setExtras(tu.getT2()); //To make it work in my local i made entity.getAttributes() as Flux<String> so here you will probably need to use .stream().map(dbItem->dbItem.getPropertyName())
dto.setPackageAttributes(tu.getT2());
return Mono.just(dto);
});
}

Nested property not found in a Spring Data query method declaration

I'm trying to use findBy... in my repository to get a Savingaccount object passing a nested attribute(name) as a parameter. Currently I'm using:
Mono<SavingAccount> findByOwnerName(String name);
but I'm getting this error: No property name found for type Owner! Traversed path: SavingAccount.owner.
My repository:
package com...SavingAccMS.Repository;
import com.everis.SavingAccMS.Model.Owner;
import com.everis.SavingAccMS.Model.SavingAccount;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import reactor.core.publisher.Mono;
public interface SavingAccountRepo extends ReactiveMongoRepository<SavingAccount, String>
{
Mono<SavingAccount> findByNumber(String number);
//This one is the problem
Mono<SavingAccount> findByOwnerName(String name);
Mono<SavingAccount> findByOwner(Owner owner);
}
My Entity:
package com...SavingAccMS.Model;
import java.security.acl.Owner;
import javax.validation.constraints.NotBlank;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.Data;
#Data
#Document(collection = "SavingAccs")
public class SavingAccount
{
#Id
private String id;
#NotBlank
private String number;
#NotBlank
private Owner owner;
#NotBlank
private String currency;
#NotBlank
private double balance = 0.00;
#NotBlank
private String status;
}
package com...SavingAccMS.Model;
import org.springframework.data.mongodb.core.mapping.Document;
import lombok.Data;
#Data
#Document(collection = "Owners")
public class Owner
{
public String dni;
public String name; //findBy this attribute is required.
}
According to your imports, the Owner in your SavingAccount refers to java.security.acl.Owner, not the one you defined yourself in om...SavingAccMS.Model.Owner. The former does not carry a name attribute.
I'm not certain but I don't think you can find the owner name in hibernate like that.
I would try the following!
#Query("SELECT * FROM SavingAccount where owner.name = :name")
Mono<SavingAccount> findByOwnerName(#Param("name") String name);

Spring Data ES query by nested object date field

Using Spring Data ES.
I have an index named ship with following definition:
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
#Document(indexName = "ship", type = "journey")
public class ShipJourney {
#Id
private String shipId;
#Field(type = FieldType.Nested)
private List<ShipLocation> shipLocation;
//getters and setters
}
ShipLocation is a nested object defined as:
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import java.time.LocalDateTime;
public class ShipLocation {
private double latitude;
private double longitude;
#Temporal(TemporalType.TIMESTAMP)
private LocalDateTime recordedOnTime;
//setters and getters
}
I want to find a ship location just before or equal to LocalDateTime parameter.
I tried this:
ShipJourney findTopByShipIdAndShipLocationRecordedOnTimeLessThanOrderByShipLocationRecordedOnTimeDesc(
String shipId, LocalDateTime recordedOnTime);
only to realise later that I was using Top on the ShipJourney itself which will be eventually one record only due to the shipId's uniqueness.
How can I limit the data I get for the nested element based on one of its attribute?
I'm not sure if it's possible with the Spring Data ElasticSearch repositories. If you can autowire ElasticSearchTemplate, your query could look something like this (untested):
String shipId = "A";
LocalDateTime recordedOnTime = LocalDateTime.now();
int maxShipLocations = 3; // <-- TOP
NestedQueryBuilder findByLocation = nestedQuery("shipLocation", rangeQuery("shipLocation.recordedOnTime").lt(recordedOnTime));
TermQueryBuilder findById = termQuery("id", shipId);
QueryBuilder findByIdAndLocation = QueryBuilders.boolQuery()
.filter(findById)
.filter(findByLocation.innerHit(new QueryInnerHitBuilder().setSize(maxShipLocations)));
SearchQuery query = new NativeSearchQueryBuilder()
.withIndices("ship")
.withTypes("journey")
.withQuery(findByIdAndLocation)
.withSort(SortBuilders.fieldSort("shipLocation.recordedOnTime").order(SortOrder.DESC))
.build();
List<ShipJourney> shipJourney = elasticSearchTemplate.queryForList(query, ShipJourney.class);

Resources