What is the ServletFilter equalent of a RabbitMq Listener? - spring-boot

I have a spring-boot web application for which I implemented an MDCFilter that adds a UUID to MDC logging context that i can find in the log file.
The Filter class looks like this.
public class MDCFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) {
}
#Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
String requestId = UUID.randomUUID().toString();
MDC.put(REQUEST_ID_KEY, requestId);
response.addHeader("trace", requestId);
try {
chain.doFilter(req, resp);
} finally {
MDC.remove("trace");
}
}
#Override
public void destroy() {
}
}
But recently we moved towards processing traffic via Queues and I have no clue from the documents to replicate this filter behaviour for the message listeners.
My listener would look something like this.
#RabbitListener(queues = "${queue1}")
public void receiveMessages(Message message) {
doTheBusinessLogic(message)
}
Can anyone point me to the right direction ?

Use the container's adviceChain. Assuming you are using Boot 2.0 and the simple container factory, override boot's factory to add the advice...
#SpringBootApplication
public class So49770881Application {
public static void main(String[] args) {
SpringApplication.run(So49770881Application.class, args);
}
#Bean(name = "rabbitListenerContainerFactory")
public SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory(
SimpleRabbitListenerContainerFactoryConfigurer configurer,
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
configurer.configure(factory, connectionFactory);
factory.setAdviceChain(new MDCAdvice());
return factory;
}
public static class MDCAdvice implements MethodInterceptor {
#Override
public Object invoke(MethodInvocation invocation) throws Throwable {
// pre process
try {
return invocation.proceed();
}
finally {
// post process
}
}
}
}

Related

Not able to set cookie samesite=none for spring boot 1.5.22

I working on spring boot 1.5.22 and i'm facing an issue with the cookies samesite=none proporty.I'm not able to set the samesite attribute for cookies because of which the oauth authentication is not working on chrome but it is working on other browser. So, I tried few solutions like this.
#Component
public class CustomizationBean implements EmbeddedServletContainerCustomizer {
#Override
public void customize(ConfigurableEmbeddedServletContainer container) {
if (container instanceof TomcatEmbeddedServletContainerFactory) {
TomcatEmbeddedServletContainerFactory factory = TomcatEmbeddedServletContainerFactory.class.cast(container);
factory.addContextCustomizers(new TomcatContextCustomizer() {
#Override
void customize(Context context) {
Rfc6265CookieProcessor cookieProcessor = new Rfc6265CookieProcessor()
cookieProcessor.setSameSiteCookies("None")
context.setCookieProcessor(cookieProcessor)
}
})
}
}
}
And that didn't help.So i tried adding a custom filter
#Component
public class SameSiteFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, response);
addSameSiteCookieAttribute((HttpServletResponse) response);
}
private void addSameSiteCookieAttribute(HttpServletResponse response) {
Collection<String> headers = response.getHeaders(HttpHeaders.SET_COOKIE);
boolean firstHeader = true;
for (String header : headers)
{
if (firstHeader) {
response.setHeader(HttpHeaders.SET_COOKIE, String.format("%s; %s", header, "SameSite=None;"));
firstHeader = false;
continue;
}
response.addHeader(HttpHeaders.SET_COOKIE, String.format("%s; %s", header, "SameSite=None;"));
}
}
#Override
public void destroy() {
}
}
I added this as addFilterBefore(new SameSiteFilter(),BasicAuthenticationFilter.class) and addFilterAfter(new SameSiteFilter(),BasicAuthencticationFilter.class)
in HttpSecurity configure
Anyway to set the SameSite=None for jsessionid
i was using embedded tomcat 8.54 which was not setting samesite to none but working for other values like lax,strict. So updated embedded the tomcat to 8.58 in which i guess they fixed that bug. So, updating tomcat version solved my problem

Intercept request & send to external

I am developing a Spring boot project.
One example of my controller:
#Controller
public class RestController {
#GetMapping(value = "/student/{studentId}")
public #ResponseBody Student getData(#PathVariable Integer studentId) {
Student student = new Student();
student.setName("Peter");
student.setId(studentId);
return student;
}
}
I have other endpoints implemented as well.
I need to intercept every request hits my endpoints & forward the request to another service (microservice), in other words, I need to forward each request to another web app running on the same local machine as current one, based on the response from that service to decide whether proceed forward the request or not.
My rough idea is to use HandlerIntercept , but I am not sure whether I am going to the right direction. Could someone please share some experiences what is the best way to achieve this? It would be nice if you could show some sample code. Thanks in advance.
You can use HandlerInterceptorAdapter.
Define the Interceptor as below.
#Component
public class RequestInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object object) throws Exception {
System.out.println("In preHandle we are Intercepting the Request");
System.out.println("____________________________________________");
//Call the Rest API and Validate
if (conditionsNotMet()) {
response.getWriter().write("something");
response.setStatus(someErrorCode);
return false;
}
}
}
Register the HandlerInterceptorAdapter
#Configuration
public class PathMatchingConfigurationAdapter extends WebMvcConfigurerAdapter {
#Autowired
private RequestInterceptor requestInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(requestInterceptor);
}
}
using WebMvcConfigurer
#Configuration
public class PathMatchingConfigurationAdapter implements WebMvcConfigurer {
#Autowired
private RequestInterceptor requestInterceptor;
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(requestInterceptor);
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry resourceHandlerRegistry) {
}
#Override
public void addCorsMappings(CorsRegistry corsRegistry) {
}
#Override
public void addViewControllers(ViewControllerRegistry viewControllerRegistry) {
}
#Override
public void configureViewResolvers(ViewResolverRegistry viewResolverRegistry) {
}
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> list) {
}
#Override
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> list) {
}
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> list) {
}
#Override
public void extendMessageConverters(List<HttpMessageConverter<?>> list) {
}
#Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> list) {
}
#Override
public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> list) {
}
#Override
public Validator getValidator() {
return null;
}
#Override
public MessageCodesResolver getMessageCodesResolver() {
return null;
}
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
}
#Override
public void configureAsyncSupport(AsyncSupportConfigurer asyncSupportConfigurer) {
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer defaultServletHandlerConfigurer) {
}
#Override
public void addFormatters(FormatterRegistry formatterRegistry) {
}
#Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(false);
}
}

Custom Spring Security Filter Test with MockMvc always returns 404

I am trying to test a custom filter using MockMvc and it always returns status 404 instead of the actual status returned from the filter class.
The filter class looks as follows:
public class CustomFilter extends GenericFilterBean {
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
// some logic
chain.doFilter(servletRequest, servletResponse);
}
}
This is registered in with the SpringBootApplication using FilterRegistrationBean
#SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
try {
ConfigurableApplicationContext ctx = SpringApplication.run(MyApplication.class, args);
} catch (Throwable e) {
}
#Bean
public FilterRegistrationBean<CustomFilter> customFilter() {
FilterRegistrationBean<CustomFilter> filterRegistration = new FilterRegistrationBean<>();
filterRegistration.setFilter(new CustomFilter());
filterRegistration.addUrlPatterns("/test/*");
return filterRegistration;
}
}
The test for this is written as follows:
#RunWith(SpringRunner.class)
#SpringBootTest(CustomFilter.class)
#EnableAutoConfiguration
#WebAppConfiguration
public class CustomFilterTest {
#Autowired
private CustomFilter filter;
#Autowired
private WebApplicationContext context;
private MockMvc mvc;
#Before
public void setup() {
this.mvc = MockMvcBuilders.webAppContextSetup(context)
.addFilters(filter)
.build();
}
#Test
public void testCustomFilter() throws Throwable {
MockHttpServletRequestBuilder request = MockMvcRequestBuilders
.request(HttpMethod.POST, "/resource/abc")
.header("SomeHeader", "xxx")
.content("{}");
MockHttpServletResponse response = mvc.perform(request).andReturn().getResponse();
assertEquals(response.getStatus(), HttpServletResponse.SC_CONTINUE);
}
}
The assertion always returns the status value of 404.
Am I missing something here?
Add urlPatterns to the addFilter(filter, "/resource/abc") and add a test controller for the above code snippet as follows:
#RestController
public class TestController {
#PostMapping("/resource/abc")
public void testSecureEndpoint() {
}
}

How to add Filter in Spring MVC Javaconfig correctly

I'm a bit confused about adding Filters in Spring MVC with JavaConfig.
For example using the ResourceUrlEncodingFilter and the ShallowEtagHeaderFilter.
I've seen people doing this
public class MvcWebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
FilterRegistration.Dynamic filterRegistration = servletContext.addFilter("resourceUrlEncodingFilter",
new ResourceUrlEncodingFilter());
filterRegistration.setInitParameter("encoding", "UTF-8");
filterRegistration.setInitParameter("forceEncoding", "true");
filterRegistration.addMappingForUrlPatterns(null, true, "/*");
}
}
(do i have to create a Filter registration for every single Filter?)
or this
#Override
protected Filter[] getServletFilters() {
return new Filter[] { new CharacterEncodingFilter() };
}
or this
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
servletContext.addFilter("name", CharacterEncodingFilter.class)
.addMappingForUrlPatterns(null, false, "/*");
}
or
public class AppConfig extends WebMvcConfigurerAdapter {
/* ... */
#Bean
public ShallowEtagHeaderFilter shallowEtagHeaderFilter() {
return new ShallowEtagHeaderFilter();
}
}
or even this:
public class AppConfig extends WebMvcConfigurerAdapter {
/* ... */
#Bean
public Filter shallowEtagHeaderFilter() {
return new ShallowEtagHeaderFilter();
}
}
(seems not to work in my app)
So what is the best approach for adding Filters and keep code clean?
(What are the differences)

Spring Boot Rest API filter not invoked

I want to implement filter on my Spring Boot Rest API project but some how my filter not invoked. I have added below implementation for that.
public class AutorizationFilter implements Filter{
Logger log = LoggerFactory.getLogger(AutorizationFilter.class);
#Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("**** Start ****");
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
log.info("**** doFilter ****");
chain.doFilter(request, response);
}
#Override
public void destroy() {
log.info("**** end ****");
}}
init and destroy method are working but doFilter method not invoke.
#Configuration
public class RestApiConfig {
#Bean
public FilterRegistrationBean<AutorizationFilter> filterRegistrationBean(){
FilterRegistrationBean<AutorizationFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new AutorizationFilter());
registrationBean.addUrlPatterns("/**");
return registrationBean;
}}
My controller is as below:
#RestController
#RequestMapping("/home")
public class HomeController {
#RequestMapping(value="/hello",method=RequestMethod.GET)
public ResponseEntity<Object> hello() {
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("data","called home controller");
return new ResponseEntity<>(resultMap,HttpStatus.OK);
}
}
Any one please help me why dofilter method is not working.
finally i found the solution, I need to replace registrationBean.addUrlPatterns("/**") with registrationBean.addUrlPatterns("/*") and it's working fine for me.

Resources