Java Agent
Overview
The NetFUNNEL Java agent is a dedicated client that communicates with the NetFUNNEL server from Java-based Spring Boot servers.
Minimum Requirements
- Java 1.7 or later
- Spring Boot 3.x or later
External Dependencies
- gson: Library for JSON serialization/deserialization
- jackson-module-kotlin: Library required for Kotlin (when using Java)
Operation Flow
Queue control points can be configured via segment trigger rules in the NetFUNNEL console. The queue is applied when the URL of the page the user accesses matches the trigger rules.
Before waiting: Page load → Agent initialization → Trigger rule match While waiting: Request to NetFUNNEL server → NetFUNNEL key issued → Redirect to waiting room page After waiting: Enter service page → Return NetFUNNEL key
Agent Installation
Add Library
Kotlin DSL (build.gradle.kts)
implementation(files'libs/netfunnel-agent.jar')
implementation(com.google.code.gson:gson:2.9.1)
implementation (com.fasterxml.jackson.module:jackson-module-kotlin)
Groovy DSL (build.gradle)
implementation files('libs/netfunnel-agent.jar')
implementation 'com.google.code.gson:gson:2.9.1'
// When using Java
implementation 'com.fasterxml.jackson.module:jackson-module-kotlin'
Applying an Interceptor
Choose only one of Interceptor or Filter to match your project structure. Both provide the same NetFUNNEL queue control behavior, so you do not need to implement both.
In the Interceptor that receives requests first, add code as follows.
Kotlin
@Component
public class DemoInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
NetFunnelInitializer initializer = getNetFunnelInitializer(requestUrl);
Netfunnel netfunnel = new Netfunnel(initializer, new NetFunnelServletService(request, response));
return netfunnel.run();
}
private NetFunnelInitializer getNetFunnelInitializer(String requestUrl) {
return NetFunnelInitializer.builder()
.clientId("{{CLIENT_ID}}")
.secretKey("{{SECRET_KEY}}")
.build();
}
}
Java
import com.stclab.Netfunnel;
import com.stclab.servlet.NetFunnelServletService;
import com.stclab.utils.NetFunnelInitialize;
@Component
public class DemoInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
NetFunnelInitialize config = NetFunnelInitialize.Companion.builder()
.clientId("{{CLIENT_ID}}")
.secretKey("{{SECRET_KEY}}")
.build();
Netfunnel netfunnel = new Netfunnel(config, new NetFunnelServletService(request, response), null, null);
return netfunnel.run();
}
}
Register the Interceptor by overriding the addInterceptors method of WebMvcConfigurer.
Kotlin
@Configuration
public class WebConfig implements WebMvcConfigurer {
private final DemoInterceptor demoInterceptor;
@Autowired
public WebConfig(DemoInterceptor demoInterceptor) {
this.demoInterceptor = demoInterceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(demoInterceptor);
}
}
Java
@Configuration
public class WebConfig implements WebMvcConfigurer {
private final DemoInterceptor demoInterceptor;
@Autowired
public WebConfig(DemoInterceptor demoInterceptor) {
this.demoInterceptor = demoInterceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(demoInterceptor)
.addPathPatterns("/**");
}
}
Applying a Filter
In the Filter that receives requests first, add code as follows.
Kotlin
@Component
public class DemoFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
NetFunnelInitializer initializer = getNetFunnelInitializer(requestUrl);
Netfunnel netfunnel = new Netfunnel(initializer, new NetFunnelServletService(request, response));
if (netfunnel.run()) {
chain.doFilter(servletRequest, servletResponse);
}
}
private NetFunnelInitializer getNetFunnelInitializer(String requestUrl) {
return NetFunnelInitializer.builder()
.clientId("{{CLIENT_ID}}")
.secretKey("{{SECRET_KEY}}")
.build();
}
}
Java
import com.stclab.Netfunnel;
import com.stclab.servlet.NetFunnelServletService;
import com.stclab.utils.NetFunnelInitialize;
public class DemoFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
NetFunnelInitialize config = NetFunnelInitialize.Companion.builder()
.clientId("{{CLIENT_ID}}")
.secretKey("{{SECRET_KEY}}")
.build();
Netfunnel netfunnel = new Netfunnel(config, new NetFunnelServletService(request, response), null, null);
if (!netfunnel.run()) {
return;
}
chain.doFilter(servletRequest, servletResponse);
}
}
Register the Filter as a bean.
Kotlin
@Configuration
@RequiredArgsConstructor
public class FilterConfig {
private final DemoFilter demoFilter;
@Bean
public FilterRegistrationBean<Filter> filterRegistrationBean() {
return new FilterRegistrationBean<>(demoFilter);
}
}
Java
@Configuration
@RequiredArgsConstructor
public class FilterConfig {
@Bean
public FilterRegistrationBean<Filter> filterRegistrationBean() {
FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
registration.setFilter(new DemoFilter());
registration.addUrlPatterns("/*");
registration.setOrder(1);
return registration;
}
}
Initialize Settings
| Field | Default | Required | Description | Agent version |
|---|---|---|---|---|
| clientId | N/A | O | Enter the client ID issued from the console. | 4.0.1 or later |
| secretKey | N/A | O | Enter the secret key issued from the console. | 4.0.1 or later |
| serverUrl | N/A | X | URL of the NetFUNNEL server. Use when accessing the server via a custom URL instead of a clientId-based URL or when not using CNAME. <br />(Supported for backward compatibility.) | 4.0.1 or later |
| settingUrl | N/A | X | URL of the NetFUNNEL environment configuration file. Use when loading the config via a custom URL instead of a clientId-based URL or when not using CNAME. <br />(Supported for backward compatibility.) | 4.0.1 or later |
| vwrPageUrl | N/A | X | URL of the NetFUNNEL VWR page. Use when redirecting to the waiting room via a custom URL instead of a clientId-based URL. | 4.0.1 or later |
| returnKey | true | X | When the user passes the queue and enters the page, the next user can enter immediately.<br />If disabled, the next user waits for a period even after the user has entered. <br />(Timeout is configured in Console: Segment settings > Advanced.) | 4.0.1 or later |
| logLevel | Level.OFF | X | Set log level based on ch.qos.logback.classic.Level; that dependency must be added.<br />Levels: ERROR, WARN, INFO, DEBUG, TRACE, OFF | 4.0.1 or later |
| goodBots | N/A | X | Exclude good bots (e.g. search engines) from NetFUNNEL entry. Pass an array of strings.<br />Example: ["Googlebot", "Bingbot"] | 4.0.1 or later |
| userId | N/A | X | When set, this ID is used for whitelist and permanent block.<br />The ID configured in Console > Repeated request block > User settings > Visitor management is applied. | 4.0.1 or later |
| vwrPageDomain | N/A | X | Use when building the VWR page URL with only the CNAME domain.<br />Example: https://vwr.example.com | 4.0.1 or later |
| cookieDomain | N/A | X | Set the domain of the NetFUNNEL cookie explicitly. | 4.0.1 or later |
Agent Application
Queue control points can be configured via segment trigger rules in the NetFUNNEL console. The queue is applied when the URL of the page the user accesses matches the trigger rules.
Configuration Options
- Logical Operator: When creating two or more trigger rules, defines their relationship with and or or.
- Validator: Defines the top-level scope for the trigger rule (e.g. URL only).
- Component: Within the scope defined by the Validator, specifies the target in more detail (e.g. full URL or path).
- Negate: Use to apply the opposite of the configured condition (e.g. when the condition is not true).
- Match: Defines the type of condition (e.g. Equals, Exists) for when the rule applies.
- Value: The value to compare against when the rule is evaluated; used together with Match.
- Aa: Whether to match Value case-sensitively.
Match Options
- Exists: Checks whether the Component exists in the URL. (Only when Component is Path.)
- Equals: Checks whether the Component value exactly matches Value.
- Contains: Checks whether the Component value contains Value.
- StartsWith: Checks whether the Component value starts with Value.
- EndsWith: Checks whether the Component value ends with Value.
Testing Trigger Rules
You can test in advance whether the URLs where you want to apply the queue match the trigger rules.