I need an Interceptor in Jersey 2.x which gives references to request, response and the Method which matched the Path to a Web Service.
Something similar to HandlerInterceptor of Spring.
Requirements:
Spring equivalent code:
public class WebServiceInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
try {
SkipWebServiceIntercept skipWebService = handler.getClass().getAnnotation(SkipWebServiceIntercept.class);
if (skipWebService != null) {
return Boolean.TRUE;
}
...
if(securityFails)
{
if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
response.setCharacterEncoding("utf-8");
response.setContentType("application/json");
PrintWriter out = response.getWriter();
String json;
...
out.println(json);
return Boolean.FALSE;
}
else {
response.sendRedirect(redirectUrl);
}
}
else
{
return Boolean.TRUE;
}
}catch (Exception e) {
log.error("Exception in preHandle, redirecting to Login page", e);
return LoginUtil.redirectToLogin(request, response);
}
}
}
I found references of
Is there anyother way this can be achieved without using Filters. because I need this processing to happen ONLY if the corresponding web-service is present. Filter's with /* on the other hand would always perform these validations even when the resource was not found.
Edit: Thanks to @peeskillet answer This is how I implemented it.
@Provider
public class ResourceInterceptor implements DynamicFeature {
@Override
public void configure(ResourceInfo resourceInfo, FeatureContext context) {
System.out.println("Resource Interceptor called");
if (resourceInfo.getResourceClass() != null
&& resourceInfo.getResourceClass().getAnnotation(SkipWebServiceIntercept.class) != null)
return;
context.register(LoginFilter.class);
}
}
@Slf4j
public class LoginFilter implements ContainerRequestFilter {
@Context
private HttpServletRequest request;
@Context
private ServletContext servletContext;
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
try {
WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
CookieAuthenticator cookieAuthenticator = springContext.getBean(CookieAuthenticator.class);
HttpSession session = request.getSession(true);
...
// Sending JSON/Object back as response
...
String json = gson.toJson(resposeJson);
Response response = new ResponseBuilderImpl().encoding(StandardCharsets.UTF_8.name())
.type(MediaType.APPLICATION_JSON).entity(json).build();
requestContext.abortWith(response);
...
// or Sending URL back
...
URI uri = new URI(baseUrl + redirectUrl + "?refback=" + url);
requestContext.abortWith(Response.temporaryRedirect(uri).build());
...
Both the approaches worked perfectly, similar to HandlerInterceptor of Spring.
Is there anyother way this can be achieved without using Filters. because I need this processing to happen ONLY if the corresponding web-service is present. Filter's with /* on the other hand would always perform these validations even when the resource was not found.
There are different ways to register a filter.
Just register it normally, where the result is the filter always getting called. (what you don't want).
Registered with an annotation, though name binding. This way, only resource annotated will go through the filter. (this is kind of what you want, only problem is you would need to annotate every class)
@Target({TYPE, METHOD})
@Retention(RetentionPolicy.RUNTIME);
class @interface Filtered {}
@Path("..")
@Filtered
public class YourResource {}
@Filtered
@Provider
public class YourFilter implements ContainerRequestFilter {}
Use a DynamicFeature to bind resource programmatically, rather than declaratively. The DynamicFeture
will get called for each of your resource methods, so you can just register the filter for every call. This has the same affect as annotating every resource class (as mentioned above) with name binding (this is probably what you want).
@Provider
public class MyFeature implements DynamicFeature {
@Override
public void configure(ResourceInfo ri, FeatureContext ctx) {
ctx.register(YourFilter.class);
}
}
See Also:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With