0

I have two entities:

Entity A:

private Long idA;

Entity B:

private Long idB;
private Long fkA;

My Micro Service can save, modify or delete only the B entity :

Repository:

@Repository
public interface BRepository extends CrudRepository<B, Long>{

}

Feign External Service:

@FeignClient(value = "aExtClient", url = "${A_EXT_MS_URL}")
public interface AExtRemoteService {

    @DeleteMapping(path = "/a/{idA}", produces = MediaType.APPLICATION_JSON_VALUE)
    public Esito deleteA(@PathVariable(name = "idA") Long idA);

}

ServiceImpl:

@Component
@Transactional(rollbackFor = BusinessServiceException.class)
public class BServiceImpl implements BService { 
    
    @Autowired
    private BRepository bRepository;
    
    @Autowired
    private AExtRemoteService aExtRemoteService;
    
    @Override
    public void deleteB(B b) {        
        
        Long idA = b.getFkA();
        
        bRepository.delete(b); //marker
        
        if(idA  != null) {
            aExtRemoteService.deleteA(idA);
        }
    }
    
}

External service can save, modify or delete only the A entity :

Controller:

@RestController
@RequestMapping("/a")
@CrossOrigin(origins = "${mocks.allowedCrossOrigins:*}")
public class AServiceMockController {

    @Autowired
    private AMockService aMockService;
    
    @DeleteMapping(value = {
            "/{idA}" }, produces = MediaType.APPLICATION_JSON_VALUE)
    public @ResponseBody ResponseEntity<Result> deleteA(@PathVariable(name = "idA") Long idA) {
        Result result = new Result();
        aMockService.deleteA(idA);
        result.setResult(true);
        result.setCod(String.valueOf(HttpStatus.OK.value()));
        result.setMess(HttpStatus.OK.name());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }

}

Service:

@Service
public class AMockService {

    private final ARepository aRepository;    

    @Autowired
    public AMockService(ARepository aRepository) {
        this.aRepository = aRepository;
    }
    
    public void deleteA(Long idA) {
        A byId = aRepository.findById(idA).orElseThrow(NoSuchElementException);
        aRepository.delete(byId);
    }

}

Repository:

@Repository
public interface ARepository extends CrudRepository<A, Long>{

}

On calling deleteB, the external service has returned this message:

Caused by: java.sql.SQLIntegrityConstraintViolationException: ORA-02292:  integrity constraint violated (X.YY) - child record found

How can I solve? Seems like it's not taking into consideration bRepository.delete(b);

P.S. I have access to the external service, so if needed I can modify it.

Paul Marcelin Bejan
  • 990
  • 2
  • 7
  • 14
  • I dont believe you gave enough information people to help, If the exception is in the external service we would need to see that code in order to help. It sounds like a has a child connected to it. you would either need to delete its children in order to delete it. Or set On Delete Cascade on the foreign key in order to delete its children automatically – bgore Nov 15 '21 at 14:24
  • @bgore i add some more code – Paul Marcelin Bejan Nov 15 '21 at 15:18

2 Answers2

2

You cannot have transactions like this across microservices - one because you are using a remote http call to service A and it is by nature not capable in participating in transaction you are initiating in service B. The transaction you are using is resource-local transaction. Second you are sharing a database in both the services and the remote http service is trying to delete a record which has a foreign key relation as a parent. Since you are using Spring transaction manager you can use a TransactionEventListener ( see here to an example usage) to invoke deleting A after your transaction in B has finished successfully. There are other patterns to solve transactions across microservices like Saga

Shailendra
  • 8,874
  • 2
  • 28
  • 37
0

The error message indicates that the delete hasn’t gone through yet. The first thing I would try is manually bRepository.flush() after the delete.

You can read about flush here: https://www.baeldung.com/spring-data-jpa-save-saveandflush

Anonymous Beaver
  • 370
  • 2
  • 10