0 Comments
0 Shares
17 Views
Directory
Elevate your Sngine platform to new levels with plugins from YubNub Digital Media!
-
Please log in to like, share and comment!
-
-
-
BLOG.JETBRAINS.COMDebugging Transactions? Let Spring Debugger Do the Heavy LiftingSpring Frameworks declarative transaction management is incredibly powerful, allowing developers to simply add the @Transactional annotation to a method and let Spring handle the transaction details. However, misconfigurations or misunderstandings of how transactions work can lead to frustrating database transaction handling issues. Debugging these problems often means sifting through a lot of AOP proxy code, which is not really a pleasant experience.This is where the Spring Debugger plugin comes to the rescue! Its designed specifically to help you identify and fix these complex transaction management and JPA-related issues, making your debugging much smoother.You can also watch the demonstration of Spring Debugger plugins database transaction debugging feature in this video.Unmasking Transactional Mysteries with Spring DebuggerLets say we are building a bookmarks management application and consider a use case creating a new bookmark, which might also involve creating a new bookmark category if it doesnt already exist. The goal is that if category creation succeeds but bookmark saving fails, only the bookmark changes should roll back, while the category creation should persist.A developer might implement this feature as follows:@Servicepublic class BookmarkService { //.... @Transactional public Bookmark createBookmark(CreateBookmarkCmd cmd) { var bookmark = new Bookmark(cmd.title(), cmd.url()); if(cmd.categoryName() != null) { Category category = categoryService.findByName(cmd.categoryName()).orElse(null); if (category == null) { category = this.createCategory(new Category(cmd.categoryName())); } bookmark.setCategory(category); } bookmarkRepository.save(bookmark); log.info("Created bookmark with id: {}", bookmark.getId()); return bookmark; } @Transactional(propagation = Propagation.REQUIRES_NEW) public Category createCategory(Category category) { category.setId(null); return categoryRepository.save(category); }}The current implementation assumes that the createBookmark() method annotated with @Transactional will start a transaction. Inside, if a category needs to be created, call createCategory() method which is annotated with @Transactional(propagation = REQUIRES_NEW), hoping it will start a new, independent transaction. The expectation is that if createBookmark() fails (e.g., due to a NULL URL), the category should still be saved.Lets validate this logic through the following test.import com.sivalabs.bookmarks.TestcontainersConfig;import org.assertj.core.api.Assertions;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.context.annotation.Import;import org.springframework.transaction.TransactionSystemException;import java.util.Optional;import static org.assertj.core.api.Assertions.assertThat;import static org.assertj.core.api.Assertions.assertThatThrownBy;@SpringBootTest@Import(TestcontainersConfig.class)class BookmarkServiceTest { @Autowired BookmarkService bookmarkService; @Autowired private CategoryRepository categoryRepository; @Test void shouldCreateCategoryEvenWhenBookmarkCreationFails() { String categoryName = "java25"; Optional<Category> categoryOptional = categoryRepository.findByNameEqualsIgnoreCase(categoryName); assertThat(categoryOptional).isEmpty(); var cmd = new CreateBookmarkCmd( "My New Article", null, categoryName); assertThatThrownBy(()-> bookmarkService.createBookmark(cmd)) .isInstanceOf(TransactionSystemException.class); categoryOptional = categoryRepository.findByNameEqualsIgnoreCase(categoryName); assertThat(categoryOptional).isNotEmpty(); }}The test will fail and the category was not saved, indicating that the intended separate transaction didnt actually occur. Why?Without Spring Debugger, figuring this out would involve painfully sifting through AOP proxy code. But with the plugin, its remarkably simple:Set breakpoints in your createBookmark() and createCategory() methods.Run your test in debug mode.As you step through the code, the Transaction node in the debug tool window provides more insights.Initial Observation: When in the createBookmark() method, the debugger shows that the database transaction started there. Crucially, even after stepping into the createCategory() method, the debugger still indicates that the code is running in the same transaction that started in createBookmark().The Revelation: This immediately highlights the problem! Even with @Transactional(propagation = REQUIRES_NEW) on createCategory(), its not starting a new transaction. The debugger helps us understand why: calling a method within the same class (a local method call) doesnt go through the AOP proxy, meaning the @Transactional annotation on that internal method is not taken into consideration. This is why both bookmark and category creation were rolling back together when createBookmark() failed.The Fix and Visual ValidationThe solution is to move the createCategory() method into a separate service (e.g., CategoryService). When the createBookmark() method then calls categoryService.createCategory(), Springs AOP proxy can intercept this call.Running the test in debug mode again with the Spring Debugger, youll see a profound difference.When in createBookmark(), the debugger shows the parent transaction starting there.When you step into CategoryService.createCategory(), the debugger now clearly indicates that the current method is running in a new transaction that started in CategoryService.createCategory().Even better, the debug window shows the hierarchy of transactions, detailing the parent transaction (BookmarkService.createBookmark()) and the newly started child transaction (CategoryService.createCategory()).You also get comprehensive information about each transaction, including its isolation level, propagation behavior, and read-only status.You can also see the entities in the Hibernates L1 cache.With this change, the code behaves as expected: if bookmark creation fails, only those changes are rolled back, and the category is successfully persisted in the database.Beyond Transactions: Visualizing JPA Entity StatesSpring Debugger isnt just for transactions. It also provides crucial visibility into JPA entity states, which can be incredibly helpful for debugging persistence-related issues.As you step through your code, the debugger can show you an entitys current state:TRANSIENT: A newly created object that has not yet been persisted to the database.DETACHED: An entity that was once managed by the persistence context but is no longer associated with it (e.g., after returning from a service method).MANAGED: An entity that is currently being tracked by the persistence context.For example, our bookmark entity starts in a TRANSIENT state. The category entity, after being created and then returning from CategoryService to BookmarkService, is shown as DETACHED.After calling bookmarkRepository.save(bookmark), the debugger shows bookmark entity state changing to MANAGED.This visualization of entity state changes is really helpful for debugging these JPA related issues.ConclusionThe Spring Debugger plugin is an indispensable tool for any Spring developer. It takes the guesswork out of debugging complex database transaction management issues by visualizing transaction flow, parent-child transaction hierarchies, and detailed transaction information. Moreover, its ability to show JPA entity state changes provides deep insights into how your data is being managed.If youve ever struggled with Spring transaction or JPA-related bugs, go ahead, install the Spring Debugger plugin today! You can find more documentation on it within IntelliJ IDEA documentation as well. Happy debugging!0 Comments 0 Shares 20 Views
-
FR.GAMERSLIVE.FRTest Drag x Drive Switch 2 : On ne s'y attendait pas !Test Drag x Drive Switch 2 : On ne s'y attendait pas !0 Comments 0 Shares 18 Views
-
Tow Tractor Market Poised for Significant Growth: Research Intelo AnalysisThe global Tow Tractor Market is witnessing remarkable expansion, driven by the increasing demand for material handling solutions across industries such as aviation, logistics, and warehousing. Tow tractors, designed for efficiently moving cargo and aircraft, have become essential for operational efficiency, safety, and productivity in these sectors. Rising global trade and e-commerce...0 Comments 0 Shares 25 Views
-
YUBNUB.NEWSCould back-to-school be the perfect time to ground your life?[View Article at Source]Energetic Health Institute Radio with Holly Whalen Back-to-school season always lights a fire under me to talk about essential oils. In my work with kids, Ive seen the right0 Comments 0 Shares 15 Views
-
YUBNUB.NEWSThe lifestyle audit: Simple swaps for a healthier home[View Article at Source]Nurses Out Loud with Melissa Schreibfeder, BSN, RN, BC-FMP Discover how small, intentional changes at home transform your health. From clean water and fresh air to non-toxic0 Comments 0 Shares 16 Views
-
YUBNUB.NEWSSNAP Ban SHOCKS StateMillions ImpactedTexass unprecedented SNAP junk food ban has ignited a national debate over government overreach and the responsible use of taxpayer dollars. Story Snapshot Texas becomes the first state to secure federal0 Comments 0 Shares 14 Views
-
YUBNUB.NEWSBeto ORourke Is The Political Wart That Wont Go Away[View Article at Source]The sugar daddy of temper-tantrum-throwing Texas Democrats appears to be ramping up for another losing political campaign.0 Comments 0 Shares 17 Views