About

DebugWebModule provides a configurable endpoint for developer related web resources from other modules. It allows other modules to register one or more debug web controllers upon the presence of the DebugWebModule. A typical example of a debug web controller would be a controller to introspect and manage the cache. Out of the box DebugWebModule comes with a set of default controllers that allow you to introspect the running AcrossContext.

1. General information

1.1. Artifact

<dependencies>
    <dependency>
        <groupId>com.foreach.across.modules</groupId>
        <artifactId>debug-web-module</artifactId>
        <version>1.0.1.RELEASE</version>
    </dependency>
</dependencies>

1.2. Module dependencies

DebugWebModule only has a required dependency on AcrossWebModule.

1.3. Module settings

All properties start with the debugWebModule. prefix.

Property Type Description Default

root-path

String

Root path for all debug web controllers. All mappings will be relative to this path.

/debug

dashboard

String

Path within the debug web context for the initial dashboard.

/

properties.masks

String[]

Set regular expressions for all property names that should be masked.

.*password.*, .*secret.*

properties.masked-properties

String[]

Set explicit property names that should be masked.

2. What’s new in this version?

1.0.1.RELEASE

  • both root path and dashboard path are now configurable through properties

  • the context browser debug controller can now mask sensitive property values

1.0.0.RELEASE

Initial public release available on Maven central.

3. How DebugWebModule works

DebugWebModule creates a new RequestMappingHandlerMapping endpoint that serves all @RequestMapping methods from beans annotated with @DebugWebController. All mappings will be prefixed with the configured root path (eg: /debug) ensuring that all web controllers are behind a base path. Under the hood, DebugWebModule achieves this by creating a specific PrefixingRequestMappingHandlerMapping instance named DebugWebModule.

All @DebugWebController instances are automatically mapped on the default debug web layout template. The template takes care of dynamically building a top menu where controllers can position themselves. For output rendering a Thymeleaf template based on Bootstrap and JQuery is used.

4. Configuring DebugWebModule

4.1. Root path

The root path is configured by setting the debugWebModule.root-path property. This can only be done when configuring the AcrossContext, before it has bootstrapped. If no custom root path is configured, the default is /debug.

4.2. Dashboard (landing page)

Pointing your web browser at the root path within your application will open DebugWebModule on the dashboard. By default the dashboard has no content other than the top menu. If you would like a particular controller to open you can set another relative path on the debugWebModule.dashboard property. The path should not contain the root path prefix.

5. Securing debug web

By default the DebugWebModule takes no care of securing the debug endpoints. This is considered the responsibility of the application itself. Securing can easily be done on a webserver level or through Spring security.

Example securing debug web with Spring security
@Configuration
public class DebugWebSecurityConfiguration extends SpringSecurityWebConfigurerAdapter
{
	@Autowired
	private DebugWeb debugWeb;

	@Override
	public void configure( AuthenticationManagerBuilder auth ) throws Exception {
		auth.inMemoryAuthentication()
			.withUser( "debug" )
			.password( "debug" )
			.roles( "DEBUG_USER" );
	}

	@Override
	public void configure( HttpSecurity http ) throws Exception {
		http.antMatcher( debugWeb.path( "/**" ) )
		    .authorizeRequests().anyRequest().hasRole( "DEBUG_USER" )
		    .and()
		    .formLogin().disable()
		    .httpBasic()
		    .and()
		    .sessionManagement().sessionCreationPolicy( SessionCreationPolicy.STATELESS )
		    .and()
		    .csrf().disable();
	}
}

6. Default debug controllers

Out of the box DebugWebModule provides some default debug controllers. These are all available through the top menu.

6.1. Section: Servlet context

Lists the servlets and filters registered on the servlet context.

6.2. Section: Across

Context browser

Allows you to introspect the running AcrossContext. You can navigate the entire ApplicationContext hierarchy, see the modules registered in the Across context along with the beans they created (and expose) as well as the configuration properties visible within each module.

As some properties contain sensitive data (for example passwords), it is possible to mask property values based on the property name. By default all property names containing password or secret will have their values masked. Additional rules can be configured with debugWebModule.properties.masks or debugWebModule.properties.masked-properties.

AcrossWebModule: Handlers and Interceptors

Handlers lists the different request mapping endoints grouped by their handler mappings. Interceptors lists the mapped and unmapped interceptors that apply to a particular handler mapping.

6.3. Section: DataSources

Lists database drivers and registered datasources with some datasource statistics.

6.4. Section: Threads and stack

Lists the current threads with their stack trace.

7. Creating your own debug controller

7.1. @DebugWebController

Debug web controllers are just like any other controller bean with RequestMapping methods, except they are annotated with @DebugWebController instead of the standard @Controller. Any bean annotated with @DebugWebController will be picked up by the DebugWebModule and will have its mappings prefixed with the debug web root path.

Simple custom debug web controller mapped on /ROOT_PATH/test
@DebugWebController
@AcrossDepends(required = "DebugWebModule")
public class DebugEhcacheController
{
	@RequestMapping(value = "/test", method = RequestMethod.GET)
	public String test() {
		return "th/mymodule/debug/test";
	}
}

7.2. Thymeleaf template

Unless a named template is specified, the default Thymeleaf template from debug web will be applied to the output. The default template will add a top menu for all registered debug web controllers. Like any Across web Thymeleaf template, this implementation requires you to put the actual output in a content fragment.

A Thymeleaf view file for my controller
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title>My test debug controller</title>
</head>
<body th:fragment="content">
	This is a test debug controller.
</body>
</html>

If you need additional javascript or custom CSS, you can register it using the WebResourceRegistry and it will automatically be added to the output by the layout template.

Adding custom CSS with the WebResourceRegistry
@DebugWebController
@AcrossDepends(required = "DebugWebModule")
public class DebugEhcacheController
{
	@ModelAttribute
	public void registerCss( WebResourceRegistry registry ) {
		registry.addWithKey( WebResource.CSS, "MyModule", "/css/mymodule/debug.css", WebResource.VIEWS );
	}

	@RequestMapping(value = "/test", method = RequestMethod.GET)
	public String test() {
		return "th/mymodule/debug/test";
	}
}

7.3. Customizing the top menu

The default layout template builds and renders a top menu. This menu is built by publishing a DebugMenuEvent. Any AcrossEventHandler - and all controllers are event handlers by default - can listen for this event and modify the menu. The menu is built using a PathBasedMenuBuilder, allowing the entire menu hierarchy to be specified using a path structure.

Note
By default the menu item path is also used as the url for the menu endpoint. All menu item urls will be processed by the debug web WebAppPathResolver and any relative path will be prefixed with the configured root path.
Example of registering a new top-level menu item pointing to /ROOT_PATH/test
@DebugWebController
@AcrossDepends(required = "DebugWebModule")
public class DebugEhcacheController
{
	@Event
	public void registerMenuItem( DebugMenuEvent event ) {
		event.builder().item( "/test", "Test controller" );
	}

	@RequestMapping(value = "/test", method = RequestMethod.GET)
	public String test() {
		return "th/mymodule/debug/test";
	}
}

7.4. Linking to debug web controllers

The actual URL endpoint of debug web controllers depends on the application-specific configured root path. When implementing custom debug web controllers you can ensure your relative links point to the correct controller by running them through the PrefixingPathContext. DebugWebModule has registered a prefixer named debugWeb, this prefixer can be used to correctly point to a debug web controller from any other controller.

Relative links from Thymeleaf views
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<title>My test debug controller</title>
</head>
<body th:fragment="content">
	Relative to debug web root path:
	* <a th:href="@{#webapp.path('/test')}">when rendered from a debug web controller</a>
	* <a th:href="@{#webapp.path('@debugWeb:/test')}">always</a>
</body>
</html>

In code the DebugWeb bean - implementation of the PrefixingPathContext - can be used to generate the correct URL.

Example of generating a debug controller redirect
@DebugWebController
@AcrossDepends(required = "DebugWebModule")
public class DebugEhcacheController
{
	@Autowired
	private DebugWeb debugWeb;

	@RequestMapping(value = "/redirect", method = RequestMethod.GET)
	public String test() {
		return debugWeb.redirect( "/test" );
	}
}

7.5. Adding custom interceptors

If you want to add interceptors only to debug web controllers, you can register them using an instance of DebugWebConfigurerAdapter or any custom PrefixingHandlerMappingConfigurer that supports the DebugWebModule mapper.

8. Customizing debug web template

DebugWebModule uses a default Thymeleaf layout template that builds the top menu and renders HTML for Bootstrap CSS and JQuery. If you wish to replace the default layout, you can wire the debugWebTemplateRegistry, register your own WebTemplateProcessor and set it as the default template for all debug web controllers. Alternatively you can specify any registered WebTemplateProcessor by name, using the @Template annotation on specific debug web controllers.

Note
Because DebugWebModule uses its own WebTemplateRegistry, only templates registered explicitly on the debugWebTemplateRegistry bean will be available.

For more details, please see the source code of com.foreach.across.modules.debugweb.config.DebugWebInterceptorsConfiguration.