最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

spring - Unable to catch Exception for a save method of Repository interface from advice aspect - Stack Overflow

programmeradmin2浏览0评论

I am trying to audit any time changes are made to a table called Book.

So, I have created an advice which will be called when ever I update a row in Book table and saves the audit details in Book_Audit table. Every thing seems to work fine but whenever there is a failure to save in Book_Audit table, it is not been captured by catch block.

This is happening only when the point-cut is involved in a transaction.

@Aspect
@Component
@Slf4j
public class BookAuditAspect {

  private transient BookAuditRepository BookAuditRepository;

  BookAuditAspect(final BookAuditRepository BookAuditRepository) {
    this.BookAuditRepository = BookAuditRepository;
  }

  @After("execution(* com.test.inventory.app.repository.BookRepository.save(..))")
  public void afterSave(JoinPoint joinPoint) {

    Object[] args = joinPoint.getArgs();
    Book book = (Book) args[0];

    ServletRequestAttributes attributes =
        (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = attributes.getRequest();

    String username = request.getHeader("username");

    BookAudit audit =
        BookAudit.builder()
            .id(book.getId())
            .title(book.getTitle())
            .author(book.getAuthor())
            .pages(book.getPages())
            .lastModifiedBy(username)
            .lastModified(LocalDateTime.now())
            .build();

    try {
      BookAuditRepository.save(audit);
    } catch (Exception e) {
      log.error("failed to save book due to error: {}", e.getMessage());
    }
  }
}

But, when I change the code to use another service class to handle Book Audit and If the bookAuditService.saveBookAudit() fails it's exception is being caught by the catch block. Aspect with Audit service class:

@Aspect
@Component
@Slf4j
public class BookAuditAspect {

  private transient BookAuditService bookAuditService;

  BookAuditAspect(final BookAuditService bookAuditService) {
    this.bookAuditService = bookAuditService;
  }

  @After("execution(* com.test.inventory.app.repository.BookRepository.save(..))")
  public void afterSave(JoinPoint joinPoint) {

    Object[] args = joinPoint.getArgs();
    Book book = (Book) args[0];

    ServletRequestAttributes attributes =
        (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = attributes.getRequest();

    String username = request.getHeader("username");

    BookAudit audit =
        BookAudit.builder()
            .id(book.getId())
            .title(book.getTitle())
            .author(book.getAuthor())
            .pages(book.getPages())
            .lastModifiedBy(username)
            .lastModified(LocalDateTime.now())
            .build();

    try {
      bookAuditService.saveBookAudit(audit);
    } catch (Exception e) {
      log.error("failed to save book due to error: {}", e.getMessage());
    }
  }
}

Here are the other Parts of the API:

Controller


@RestController
public class BookController {

  private final BookService bookService;

  public BookController(BookService bookService) {
    this.bookService = bookService;
  }

  @PostMapping("/save-book")
  public void saveBook(@RequestBody Book book) {
    bookService.saveBook(book);
  }
}

Book Service Interface

public interface BookService {

   void saveBook(Book book);

}

Book Service Implementation

@Service
public class BookServiceImpl implements BookService {

  private final BookRepository bookRepository;

  public BookServiceImpl(BookRepository bookRepository) {
    this.bookRepository = bookRepository;
  }

  @Transactional
  public void saveBook(Book book) {
    bookRepository.save(book);
  }
}

Book Audit Service Interface

public class BookAuditService {

    public void saveBookAudit(BookAudit bookAudit) {}
}

Book Audit Service Implementation

@Service
public class BookAuditServiceImpl extends BookAuditService {

  private BookAuditRepository bookAuditRepository;

  public BookAuditServiceImpl(BookAuditRepository bookAuditRepository) {
    this.bookAuditRepository = bookAuditRepository;
  }

  @Transactional(propagation = Propagation.REQUIRES_NEW)
  public void saveBookAudit(BookAudit bookAudit) {
    bookAuditRepository.save(bookAudit);
  }
}

Book Entity

@Entity
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "Book", schema = "Library")
public class Book {

    @Id
    private Long id;

    private String title;

    private String author;

    private Integer pages;
}

Book Audit Entity

@Entity
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "Book_Audit", schema = "Library")
public class BookAudit {

  @Id private Long id;

  private String title;

  private String author;

  private Integer pages;

  private LocalDateTime lastModified;

  private String lastModifiedBy;
}

I tried to understand why this is the case, But I was not able to get any satisfactory answer. Please anyone help me what is happening in this scenario.

Thanks in advance.

发布评论

评论列表(0)

  1. 暂无评论