{"id":596461,"date":"2025-09-17T12:14:19","date_gmt":"2025-09-17T11:14:19","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=idea&#038;p=596461"},"modified":"2026-01-30T10:47:41","modified_gmt":"2026-01-30T09:47:41","slug":"spring-debugger-applicationcontext-at-your-fingertips","status":"publish","type":"idea","link":"https:\/\/blog.jetbrains.com\/zh-hans\/idea\/2025\/09\/spring-debugger-applicationcontext-at-your-fingertips","title":{"rendered":"Spring Debugger: ApplicationContext at Your Fingertips"},"content":{"rendered":"\n<p>IntelliJ IDEA has great support for debugging Java and Kotlin applications. But if you are building Spring Boot applications, you may want to access Spring components along with their metadata. That&#8217;s where the <a href=\"https:\/\/plugins.jetbrains.com\/plugin\/25302-spring-debugger\" target=\"_blank\" rel=\"noopener\">Spring Debugger<\/a> plugin comes in. It makes life easier by letting you explore and use the entire Spring ApplicationContext right from your debugger.<\/p>\n\n\n\n<p>Let&#8217;s dive into how this powerful plugin can revolutionize your debugging workflow.<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"Spring Debugger: Application Context At Your Finger Tips\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/kjVyyGiUoM0?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><figcaption class=\"wp-element-caption\">Spring Debugger: ApplicationContext at Your Fingertips <\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Beyond the Scope: Access Any Spring Bean<\/h2>\n\n\n\n<p>Imagine you are building a bookmarks management <a href=\"https:\/\/github.com\/sivaprasadreddy\/spring-debugger-demo\" target=\"_blank\" rel=\"noopener\">application<\/a> using Spring Boot and you have a Spring bean <code>BookmarkService<\/code> with <code>createBookmark()<\/code> method as follows:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">@Service\npublic class BookmarkService {\n   private final BookmarkRepository bookmarkRepository;\n   private final CategoryService categoryService;\n\n   public BookmarkService(BookmarkRepository bookmarkRepository,\n                          CategoryService categoryService) {\n       this.bookmarkRepository = bookmarkRepository;\n       this.categoryService = categoryService;\n   }\n\n   @Transactional\n   public Bookmark createBookmark(CreateBookmarkCmd cmd) {\n       var bookmark = new Bookmark(cmd.title(), cmd.url());\n       if(cmd.categoryName() != null) {\n           Category category = categoryService.findByName(cmd.categoryName()).orElse(null);\n           if (category == null) {\n               category = categoryService.createCategory(new Category(cmd.categoryName()));\n           }\n           bookmark.setCategory(category);\n       }\n       bookmarkRepository.save(bookmark);\n       return bookmark;\n   }\n}<\/pre>\n\n\n\n<p>The <code>BookmarkService<\/code> has <code>BookmarkRepository<\/code> and <code>CategoryService<\/code> beans injected. While creating a bookmark, we first check if there is a Category exists with the given name. If not, we will create a new Category and then save Bookmark.<\/p>\n\n\n\n<p>The <code>CategoryService<\/code> is also a Spring bean with <code>findByName(String)<\/code> method as follows:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">@Service\npublic class CategoryService {\n   private final CategoryRepository categoryRepository;\n\n   public CategoryService(CategoryRepository categoryRepository) {\n       this.categoryRepository = categoryRepository;\n   }\n\n   @Cacheable(\"category-by-name\")\n   public Optional&lt;Category> findByName(String name) {\n       return categoryRepository.findByNameEqualsIgnoreCase(name);\n   }\n}<\/pre>\n\n\n\n<p>The <code>findByName()<\/code> method is annotated with <code>@Cacheable(\"category-by-name\")<\/code> to cache the method result so that if you call this method with the same input it will return the cached result instead of executing the method logic again.<\/p>\n\n\n\n<p>Now, Imagine you&#8217;re debugging create bookmark use case. You hit a breakpoint in <code>BookmarkService.createBookmark()<\/code> method. Usually, you can access objects within the current scope, such as <code>bookmarkRepository<\/code>, <code>bookmark<\/code>, or <code>categoryService<\/code>.&nbsp;<\/p>\n\n\n\n<p>But what if you need to inspect or interact with a bean that isn&#8217;t directly injected into your current class. For example, you may want to clear existing data or insert new data into the database by using a repository directly.<\/p>\n\n\n\n<p>Let\u2019s say while debugging <code>BookmarkService.createBookmark()<\/code> method, we would like to temporarily delete all the categories using <code>CategoryRepository.deleteAll()<\/code>? Usually, you&#8217;d be out of luck.<\/p>\n\n\n\n<p>This is where the Spring Debugger plugin shines. It allows you to access any Spring bean that exists within your <code>ApplicationContext<\/code>. Simply start typing the bean name into the expression input box, and the plugin will show matching beans. You can then invoke any methods on them, like calling <code>categoryRepository.findAll()<\/code> method and you can view the result.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/SD-invoke-bean-method.mp4\"><\/video><\/figure>\n\n\n\n<p>This capability extends your debugging reach far beyond the immediate scope.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Manipulate Application State On-the-Fly<\/h2>\n\n\n\n<p>Consider a common scenario: you have a service method, like <code>CategoryService.findByName()<\/code>, that caches its results. If you&#8217;re debugging an issue related to this method and call it repeatedly with the same input, the breakpoint won&#8217;t be hit because the results are served from the cache.<\/p>\n\n\n\n<p>Traditionally, you might need to restart your application or temporarily disable caching to force the breakpoint to hit. With the Spring Debugger plugin, there&#8217;s a much more elegant solution.<\/p>\n\n\n\n<p>You can directly access the <code>cacheManager<\/code> bean from your <code>ApplicationContext<\/code>. Inspect the available caches, find the specific cache (e.g., category-by-name), and then invoke the <code>invalidate()<\/code> method on it.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/SD-invalidate-cache.mp4\"><\/video><\/figure>\n\n\n\n<p>After invalidating the cache, when you resume execution, the breakpoint in <code>CategoryService<\/code> will now be hit because there&#8217;s no entry in the cache for that name.<\/p>\n\n\n\n<p>This demonstrates the incredible power to invoke any method on any Spring bean to dynamically control and debug your application&#8217;s flow.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Access Core Spring Components and Properties<\/h2>\n\n\n\n<p>Sometimes we may get tricky problems due to configuration issues or misunderstanding of conventions. While debugging such issues, we may want to explore the application\u2019s runtime configuration or access low-level components to interact with database or publish application events using <code>ApplicationEventPublisher<\/code>.<\/p>\n\n\n\n<p>The utility of the Spring Debugger plugin isn&#8217;t limited to your custom beans. It also provides <strong>direct access to core Spring components<\/strong> that are part of your <code>ApplicationContext<\/code>:<\/p>\n\n\n\n<ul>\n<li><strong>EntityManager<\/strong>: If you&#8217;re using JPA, you can directly access the <code>entityManager<\/code> and invoke any methods on it.<\/li>\n\n\n\n<li><strong>Environment<\/strong>: Gain access to the <code>environment<\/code> bean, which provides an abstraction to all application properties. You can query specific property values to see their current configuration.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2025\/09\/SD-em-env.mp4\"><\/video><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Streamline Your Debugging Workflow and Save Time<\/h2>\n\n\n\n<p>The ability to access any Spring bean has significant implications for your overall debugging process.<\/p>\n\n\n\n<ul>\n<li><strong>Eliminate Temporary Code Changes<\/strong>: How many times have you temporarily injected a bean, added log statements, or introduced other debugging code, only to have to remove it once the issue is found? With Spring Debugger, you don&#8217;t need to make those temporary changes. You can directly access any bean and explore your use case as needed.<\/li>\n<\/ul>\n\n\n\n<ul>\n<li><strong>Effortless Test Data Setup<\/strong>: Imagine debugging a scenario that requires specific test data, perhaps an action only an administrator can perform. Instead of logging out, and logging in as an administrator, performing the action, and then returning to your debug flow, you can simply access a service bean directly to insert test data into the database, bypassing complex setup steps.<br><\/li>\n<\/ul>\n\n\n\n<p>In essence, the Spring Debugger plugin empowers you with all the power of the Spring <code>ApplicationContext<\/code> right at your fingertips while debugging. It significantly enhances your ability to understand, inspect, and manipulate your Spring Boot application&#8217;s state, making your debugging sessions more efficient and productive.<\/p>\n\n\n\n<p>Go ahead and install the <a href=\"https:\/\/plugins.jetbrains.com\/plugin\/25302-spring-debugger\" target=\"_blank\" rel=\"noopener\">Spring Debugger<\/a> plugin to explore its powers yourself!<\/p>\n","protected":false},"author":1517,"featured_media":620976,"comment_status":"closed","ping_status":"closed","template":"","categories":[4759,5088],"tags":[263,40,6333,8909],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/idea\/596461"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/idea"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/types\/idea"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/users\/1517"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/comments?post=596461"}],"version-history":[{"count":9,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/idea\/596461\/revisions"}],"predecessor-version":[{"id":621031,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/idea\/596461\/revisions\/621031"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/media\/620976"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/media?parent=596461"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/categories?post=596461"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/tags?post=596461"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/cross-post-tag?post=596461"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}