Issue
I'm building a Spring Boot app using CosmosDB as my database. All functions work (creating an item, updating one, get all, get by id,...), apart from delete functions. They don't do anything and since their output is void, it doesn't give me any logs either.
package projects.trashcanapplication.trashcan.dao;
import com.azure.spring.data.cosmos.core.mapping.Container;
import com.azure.spring.data.cosmos.core.mapping.GeneratedValue;
import com.azure.spring.data.cosmos.core.mapping.PartitionKey;
import org.springframework.data.annotation.Id;
import projects.trashcanapplication.trashcan.models.Address;
import projects.trashcanapplication.trashcan.models.FillStatus;
@Container(containerName = "trashcanData")
public class TrashcanDao{
@GeneratedValue
private String attachments;
private FillStatus fillStatus;
@GeneratedValue
private String rid;
private Address address;
@Id
@PartitionKey
@GeneratedValue
private String id;
@GeneratedValue
private String self;
@GeneratedValue
private String etag;
@GeneratedValue
private int ts;
public TrashcanDao(Address address, FillStatus fillStatus) {
this.fillStatus = fillStatus;
this.address = address;
}
public String getAttachments(){
return attachments;
}
public FillStatus getFillStatus(){
return fillStatus;
}
public String getRid(){
return rid;
}
public Address getAddress(){
return address;
}
public String getId(){
return id;
}
public String getSelf(){
return self;
}
public String getEtag(){
return etag;
}
public int getTs(){
return ts;
}
}
The repository
package projects.trashcanapplication.trashcan.repositories;
import com.azure.spring.data.cosmos.repository.ReactiveCosmosRepository;
import projects.trashcanapplication.trashcan.dao.TrashcanDao;
public interface TrashcanRepository extends ReactiveCosmosRepository<TrashcanDao, String> {
}
The service calling the repository
package projects.trashcanapplication.trashcan.services;
import com.azure.cosmos.models.PartitionKey;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import projects.trashcanapplication.trashcan.dao.TrashcanDao;
import projects.trashcanapplication.trashcan.models.Trashcan;
import projects.trashcanapplication.trashcan.repositories.TrashcanRepository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@Slf4j
@Service
@AllArgsConstructor
public class TrashcanServiceImpl implements TrashcanService {
private final TrashcanRepository trashcanRepository;
private final TrashcanMapper trashcanMapper;
public Flux<Trashcan> getAllTrashcans() {
return trashcanRepository.findAll().map(trashcanMapper::fromDaoToTrashcan);
}
public Mono<Trashcan> getTrashcanById(String id) {
return trashcanRepository.findById(id).map(trashcanMapper::fromDaoToTrashcan);
}
public String createTrashcan(Trashcan trashcan) {
TrashcanDao saveTrashcan = trashcanMapper.fromTrashcanToDao(trashcan);
trashcanRepository.save(saveTrashcan).subscribe();
return saveTrashcan.getId();
}
public void deleteTrashcan(String id) {
trashcanRepository.deleteById(id, new PartitionKey(id));
log.info(String.format("Deleted trashcan %s", id));
}
}
I have a dataloader temporarily set up to populate my DB with an item upon running the app. The deleteAll() function doesn't work here either.
package projects.trashcanapplication.trashcan.services;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import projects.trashcanapplication.trashcan.dao.TrashcanDao;
import projects.trashcanapplication.trashcan.models.Address;
import projects.trashcanapplication.trashcan.models.FillStatus;
import projects.trashcanapplication.trashcan.repositories.TrashcanRepository;
import javax.annotation.PostConstruct;
@Slf4j
@Component
@AllArgsConstructor
public class DataLoader {
private final TrashcanRepository trashcanRepository;
@PostConstruct
void loadData() {
Address address1 = new Address("Begijnendijk", "3130", "Liersesteenweg", "181");
trashcanRepository.deleteAll();
trashcanRepository.save(new TrashcanDao(address1, FillStatus.EMPTY))
.flatMap(trashcanRepository::save)
.thenMany(trashcanRepository.findAll())
.subscribe(trashcan -> log.info(trashcan.getId().toString()))
;
}
}
Solution
You're not subscribing anywhere, so the reactive stream isn't executed.
You could solve that by subscribing manually:
trashcanRepository.deleteAll().subscribe()
However, this is not a good practice, and certainly not in your DataLoader
as you can't guarantee the order in which the save/delete-logic is executed (maybe the TrashcanDao
is saved before you delete everything).
To solve this, you should create a proper reactive stream:
trashcanRepository
.deleteAll()
.then(trashcanRepository.save(new TrashcanDao(address1, FillStatus.EMPTY)))
.thenMany(trashcanRepository.findAll())
// Your previous subscribe() shouldn't compile since it should contain List<TrashcanDao>
.subscribe(trashcans -> log.info(trashcans.size()));
Answered By - g00glen00b
Answer Checked By - Katrina (JavaFixing Volunteer)