This question already has an answer here:
I have simplified our production application to reproduce the errors.
This is a demo application to calculate the counts of incoming requests.
when I debugged the project, I can see Null Pointer Exception
being thrown at
manager.incrementRequestCounter(url)
line in CounterMetricsFilter
class shown below. That is because manager I have autowired
is NULL.
However, the same manager autowired
in CounterController
is NOT null. I confirmed this through debugger.
what is wrong here? can filters
not be beans
? how can I get to this to work without using web.xml
in Spring MVC
application.
Thanks
Controller
@Controller
@RequestMapping("/counter")
public class CounterController {
@Autowired
CounterManager manager;
@RequestMapping(value = "/counterMetrics", method = RequestMethod.GET)
@ResponseBody
public Map getFeatureStatus(final HttpServletResponse response) {
System.out.println("returning feautre status");
return manager.getQueryCounts();
}
}
Manager
@Service
public class CounterManager {
private Map<String,Integer> queryCounts =
new ConcurrentHashMap<String,Integer>(1000);
int threshold;
long timestamp;
@Autowired
public CounterManager(@Value("${healthThreshold: 10}")
int threshold) {
this.threshold = threshold * MEGABYTES;
this.timestamp = System.currentTimeMillis();
}
public void incrementRequestCounter(String urlPath){
Integer oldVal, newVal;
do {
oldVal = queryCounts.get(model);
newVal = (oldVal == null) ? 1 : (oldVal + 1);
} while (!queryCounts.replace(model, oldVal, newVal));
}
public Map<StatusUrlModel, Integer> getQueryCounts() {
return queryCounts;
}
}
Filter
@Order(Ordered.HIGHEST_PRECEDENCE)
@Component
public class CounterMetricsFilter extends OncePerRequestFilter {
@Autowired
CounterManager manager;
public CounterMetricsFilter(){
}
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain chain) throws ServletException,
IOException {
String path = new UrlPathHelper().getPathWithinApplication(request);
try {
chain.doFilter(request, response);
}
finally {
recordMetrics(request, path);
}
}
private void recordMetrics(String path) {
try {
manager.incrementRequestCounter(url);
}
catch (Exception ex){
System.out.println("exception is thrown " + ex.getCause());
ex.printStackTrace();
}
}
}
Update:
The get the following printed on console:
exception is thrown null
(coming from CounterMetricsFilter above).
stackTrace:
java.lang.NullPointerException
at com.myapp.filter.CounterMetricsFilter.recordMetrics(CounterMetricsFilter.java:81)
at com.myapp.filter.CounterMetricsFilter.doFilterInternal(CounterMetricsFilter.java:63)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at com.myapp.filter.RequestWrapperFilter.doFilter(RequestWrapperFilter.java:24)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at com.myapp.filter.GCCORSFilter.doFilter(GCCORSFilter.java:37)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
A filter is instantiated by the servlet container so
@Autowired
is useless.You can use a
DelegatingFilterProxy
to let Spring instantiate the filter:I think you need to remove the default constructor and leave only the one with
@Autowired
dependency. Otherwise the@Component
is likely created with the default constructor and the dependency is not@Autowired
.I.e. just delete this piece of code: