How to get dispatcher servlet name in Spring controller - java

Below is my web.xml
<servlet>
<servlet-name>DispatcherName</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/spring/webmvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Is there any way that I can get the servlet-name "DispatcherName" in my application controller?
I want this to access the controller objects from the XMLWebApplicationContext & to do that I need the RequestDispatcher Name.
Till now this is what I've tried:
webApplicationContext=WebApplicationContextUtils.getWebApplicationContext(GetServletContextWebListner.getServletContext());
XmlWebApplicationContext xmlWebApplicationContext = (XmlWebApplicationContext)GetServletContextWebListner.getServletContext().getAttribute("org.springframework.web.servlet.FrameworkServlet.CONTEXT."+webApplicationContext.getApplicationName().replace("/", ""));
and tried this too
#WebListener
public class GetServletContextWebListner implements ServletContextListener {
private static ServletContext servletContext;
public static ServletContext getServletContext() {
return servletContext;
}
#Override
public void contextInitialized(ServletContextEvent sce) {
servletContext = sce.getServletContext();
}
#Override
public void contextDestroyed(ServletContextEvent sce) {
servletContext = null;
}
}
and
(XmlWebApplicationContext)GetServletContextWebListner.getServletContext().getServletContextName()
Since I'm not able to get the servlet name, I'm using the getApplicationName() but this may vary with the servlet name.

in you controller, you may try :
request.getServletContext().getServletContextName()
Or
RequestContextUtils.getWebApplicationContext(request).getDisplayName()

Related

#Provider resource not registering in rest application

I am trying to register an interceptor for my rest application. The purpouse of this interceptor is to get a token inside the request to validate if the request is valid or not.
I have created a custom tag to achieve this:
#Provider
#Secured
public class AuthenticationFilter implements ContainerRequestFilter{
private static final Logger LOGGER = Logger.getLogger(AuthenticationFilter.class);
UserDAO userDAO = (UserDAO) SpringApplicationContext.getBean("userDAO");
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// Get the HTTP Authorization header from the request
String authorizationHeader =
requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
// Check if the HTTP Authorization header is present and formatted correctly
if (authorizationHeader == null || !authorizationHeader.startsWith("BSC")) {
if (authorizationHeader== null){
LOGGER.error("No authorization header");
} else{
LOGGER.error("Authorization header: " + authorizationHeader);
}
throw new NotAuthorizedException("Authorization header must be provided");
}
// Extract the token from the HTTP Authorization header
String token = authorizationHeader.substring("BSC".length());
// Validate the token
boolean ok = validateToken(token);
if (!ok){
LOGGER.error("Not authorized, passed token: " + token);
throw new NotAuthorizedException("Not authorized");
}
}
private boolean validateToken(String token){
boolean ok = userDAO.validateToken(token);
if (ok){
userDAO.updateToken(token);
}else{
userDAO.deleteToken(token);
}
return ok;
}
}
#NameBinding
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.TYPE, ElementType.METHOD})
public #interface Secured {
}
All of the methods with the #Secured tag must pass throught the interceptor.
I have registered the interceptor and the rest service in a class that extends Application:
public class RestApplication extends Application{
private Set<Object> singletons = new HashSet<Object>();
public RestApplication() {
singletons.add(new RestService());
singletons.add(new AuthenticationFilter());
}
#Override
public Set<Object> getSingletons() {
return singletons;
}
}
Then in my web.xml I have registered this class:
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Manufacturing</display-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>
com.sun.jersey.spi.container.servlet.ServletContainer
</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.everis.manufacturing.application.RestApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
But it not seems to work, I am calling a service that have the #Secured tag but it isnĀ“t calling the interceptor.
Thanks in advance!
try changing the class RestApplication to extend ResourceConfig instead of Application.

java - throwExceptionIfNoHandlerFound not works

I'm trying to handle 404 error using an #ControllerAdvice in a Spring MVC application totally configured using Java configuration.
Here you have my conf:
public class WebAppInitializer implements WebApplicationInitializer
{
#Override
public void onStartup(ServletContext container)
{
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext();
dispatcherServlet.register(WebMvcConfig.class);
dispatcherServlet.setServletContext(container);
dispatcherServlet.refresh();
CookieHelper cookie = (CookieHelper) dispatcherServlet.getBean("cookie");
final Gson gson = (Gson) dispatcherServlet.getBean("gson");
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherServlet));
dispatcher.addMapping("/");
dispatcher.setLoadOnStartup(1);
dispatcher.setInitParameter("throwExceptionIfNoHandlerFound", "true");
FilterRegistration.Dynamic filter = container.addFilter("BaseFilter", new BaseFilter(cookie, gson));
filter.setInitParameter("forceEncoding", "true");
filter.addMappingForUrlPatterns(null, true, "/coolers/*");
filter.addMappingForUrlPatterns(null, true, "/hothouses/*");
filter.addMappingForUrlPatterns(null, true, "/lang/*");
filter.addMappingForUrlPatterns(null, true, "/organizations/*");
filter.addMappingForUrlPatterns(null, true, "/reworks/*");
filter.addMappingForUrlPatterns(null, true, "/select/*");
filter.addMappingForUrlPatterns(null, true, "/volumes/*");
}
}
and my GlobalExceptionHandlerController:
#ControllerAdvice
public class GlobalExceptionHandlerController
{
#ExceptionHandler(NoHandlerFoundException.class)
#ResponseStatus(HttpStatus.NOT_FOUND)
public String handle() {
System.out.println("test test test test");
return "error/index";
}
}
NoHandlerFoundException not firing?
I had the same issue, got it resolved. Below given steps to solve the same.
Create a class GlobalExceptionHandler annotated with #ControllerAdvice
#ControllerAdvice
public class GlobalExceptionHandler
{
#ExceptionHandler(NoHandlerFoundException.class)
public String handleNotFoundError(Exception ex)
{
return "redirect:/yourCustom404page";
}
}
By default, when a page/resource does not exist the servlet container will render a default 404 page. If you want a custom 404 response then you need to tell DispatcherServlet to throw the exception if no handler is found. We can do this by setting the throwExceptionIfNoHandlerFound servlet initialization parameter to true
a. If spring-mvc java based configuration is
public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer
{
...
#Override
protected DispatcherServlet createDispatcherServlet(WebApplicationContext servletAppContext)
{
final DispatcherServlet servlet = (DispatcherServlet) super.createDispatcherServlet(servletAppContext);
servlet.setThrowExceptionIfNoHandlerFound(true);
return servlet;
}
}
b. if spring-mvc xml based configuration, initialize your dispatcher servlet like this
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>throwExceptionIfNoHandlerFound</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
c. if spring-boot
spring.resources.add-mappings=false in your application.properties or yaml file.
Hope it helps

how to restrict the access to service in different modules

My requirement is to call the services from two different modules.But, Some urls can allow both modules,some urls allow for specific to that module.
Below is my current configuration for achieving that
<servlet>
<servlet-name>animals</servlet-name>
<servlet-class>
org.glassfish.jersey.servlet.ServletContainer
</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.lion,com.dog</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>animals</servlet-name>
<url-pattern>/lion/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>animals</servlet-name>
<url-pattern>/dogs/*</url-pattern>
</servlet-mapping>
For example if I have a service called as 'barking' this service is located in com.dog package.Now i can call this service using two urls like below
/lions/barking
/dogs/barking
As per my requirement /lions/barking should show 404 error.But it gives the response.
But some url both should work.Irrespective of where the service is located.
/lions/eat
/dogs/eat
How to do the configuration to achieve that functionality
Any help will be greatly appreciated!!!!
Use a "http Servlet Request Filter" to customise and configure/serve the requests as per your business requirements.
Please find the sample code below:
public class RequestUrlFilter implements Filter {
private static List<String> validUrls = new ArrayList<>();
public void init(FilterConfig filterConfig) throws ServletException {
//Load the valid list of urls here
validUrls.add("/lions/eat");
validUrls.add("/dogs/eat");
validUrls.add("/dogs/barking");
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain)
throws IOException, ServletException {
if(validUrls.contains(((HttpServletRequest)request).getRequestURI()) {
filterChain.doFilter(request,response);
} else {
//Error Response
RequestDispatcher rd = (HttpServletRequest)request.getRequestDispatcher("Error.jsp");
rd.forward(request, response);
}
}
public void destroy() {
}
}

Spring Rest Json Service inside a Felix OSGi container

So im trying to create a remote Rest (JSON) service inside an OSGi bundle based in Felix with Maven.
my basic service interface :
#Controller
#RequestMapping("/s/fileService")
public interface RestFileService {
#RequestMapping(value = "/file", method = RequestMethod.POST)
#ResponseBody
public String getFile(Long id);
}
My implementation of the interface
public class RestFileServiceImpl implements RestFileService{
public String getFile(Long id) {
return "test service";
}
}
Normally i would add this to my web.xml
<servlet>
<servlet-name>spring-mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/application-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring-mvc-dispatcher</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
And this would work fine inside a normal webapp.
But now i want to put this inside an OSGi bundle.
Servlet 3.0 allows you to use #WebServlet to declare a servlet without the web.xml
So i created a RestServlet
#WebServlet(value="/rest", name="rest-servlet")
public class RestServlet implements ServletContextListener {
private static Log sLog = LogFactory.getLog(RestServlet.class);
public void contextInitialized(ServletContextEvent arg0) {
sLog.info("initializing the Rest Servlet");
}
public void contextDestroyed(ServletContextEvent arg0) {
sLog.info("un-initializing the Rest Servlet");
}
}
This is my OSGi activator:
public class Activator implements BundleActivator {
private static Log sLog = LogFactory.getLog(Activator.class);
public void start(BundleContext context) throws Exception {
/*
* Exposing the Servlet
*/
Dictionary properties = new Hashtable();
context.registerService(RestFileService.class.getName(), new RestFileServiceImpl(), properties );
sLog.info("Registered Remote Rest Service");
}
public void stop(BundleContext context) throws Exception {
sLog.info("Unregistered Remote Rest Service");
}
}
I know Felix has its own http implementation with JAX but im trying to do this with spring annotations and as little XML as possible.
Can i force it to register the annotation driven 3.0 servlet ?
What am i doing wrong ? is this even possible ?
If you're looking for an easy way to do REST in OSGi, take a look at some of the web components provided by the Amdatu project. This page pretty much explains how to create a REST service: https://amdatu.org/application/web/ and there is also a video which will talk you through the whole process: https://amdatu.org/generaltop/videolessons/

Routing request to matching pages using guice servlets

I am developing inherited jsp/java ee application and I would like to introduce Guice IoC container to my application. However, I found some obstacles. I can't translate web.xml entries into guice registrations if there are more then one routing to single servlet using different urls. Problem is with init-parameters.
Here are some extracts from my web.xml:
This one is unrelated to problem, but it is good example how we are using init parameters. Basically it maps users with different roles in systems to appropriate pages.
<!-- LIST INTERNSHIPS SERVLET -->
<servlet>
<servlet-name>ListInternships</servlet-name>
<servlet-class>pl.poznan.put.ims.controllers.ListInternships</servlet-class>
<init-param>
<param-name>CoordinatorPage</param-name>
<param-value>WEB-INF/pages/coordinator/listinternships.jsp</param-value>
</init-param>
<init-param>
<param-name>MentorPage</param-name>
<param-value>WEB-INF/pages/mentor/listinternships.jsp</param-value>
</init-param>
<init-param>
<param-name>AdministratorPage</param-name>
<param-value>WEB-INF/pages/administrator/listinternships.jsp</param-value>
</init-param>
<init-param>
<param-name>AllowedRoles</param-name>
<param-value>Coordinator, Mentor, Administrator</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ListInternships</servlet-name>
<url-pattern>/internships</url-pattern>
</servlet-mapping>
Those two are the troublesome ones:
<!-- CHANGE PASSWORD SERVLET -->
<servlet>
<servlet-name>ChangePassword</servlet-name>
<servlet-class>myapp.controllers.ContextForwarder</servlet-class>
<init-param>
<param-name>SharedPage</param-name>
<param-value>WEB-INF/pages/shared/password.jsp</param-value>
</init-param>
<init-param>
<param-name>AllowedRoles</param-name>
<param-value>*</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ChangePassword</servlet-name>
<url-pattern>/changepassword</url-pattern>
</servlet-mapping>
<!-- HELP SERVLET -->
<servlet>
<servlet-name>Help</servlet-name>
<servlet-class>myapp.controllers.ContextForwarder</servlet-class>
<init-param>
<param-name>SharedPage</param-name>
<param-value>WEB-INF/pages/help/help.jsp</param-value>
</init-param>
<init-param>
<param-name>AllowedRoles</param-name>
<param-value>*</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Help</servlet-name>
<url-pattern>/help</url-pattern>
</servlet-mapping>
Here is my servlet:
#Singleton
public class ContextForwarder extends HttpServlet {
private static final long serialVersionUID = 1L;
private final IUserDao dao;
#Inject
public ContextForwarder(IUserDao dao) {
this.dao = dao;
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//trying to get rid of statics, using Ioc
Validator.checkUserLoggedIn (request);
Validator.checkUserAuthorized(this, request);
User currentUser = UserManager.getCurrentUser(request);
//pick matching page for user
String userViewPage = ServletUtils.getUserURL(this, currentUser, "Page");
try {
dao.openSession();
dao.beginTransaction();
currentUser = UserManager.reloadCurrentUser(request, dao);
ServletUtils.forward(request, response, userViewPage);
dao.commit();
}
catch(ServletException e) {
dao.rollback();
throw e;
}
catch(Exception e) {
dao.rollback();
throw new ServletException(e);
}
finally {
dao.closeSession();
}
}
}
public class ServletUtils {
public static void forward(HttpServletRequest request, HttpServletResponse response, String location)
throws ServletException, IOException {
RequestDispatcher view = request
.getRequestDispatcher( response.encodeRedirectURL(location) );
view.forward(request, response);
}
public static String getUserParameter(GenericServlet servlet, User user, String suffix) {
return servlet.getInitParameter( user.getRoles() + suffix );
}
public static String getUserURL(GenericServlet servlet, User user, String suffix)
throws ResourceNotFoundException {
String URL = getUserParameter(servlet, user, suffix);
if(URL == null) {
URL = servlet.getInitParameter("Shared" + suffix);
if(URL == null)
throw new ResourceNotFoundException(suffix);
}
return URL;
}
public static void redirect(HttpServletRequest request, HttpServletResponse response, String location)
throws ServletException, IOException {
response.sendRedirect( response.encodeRedirectURL(location) );
}
}
When i try to translate it into guice (and then register this module):
public class MyServletModule extends ServletModule
{
#Override
protected void configureServlets() {
configureHelp();
configurePassword();
}
private void configureHelp()
{
Map<String, String> params = new HashMap<String, String>();
params.put("SharedPage", "WEB-INF/pages/shared/help.jsp");
params.put("AllowedRoles", "*");
serve("/help").with(ContextForwarder.class, params);
}
private void configurePassword()
{
Map<String, String> params = new HashMap<String, String>();
params.put("SharedPage", "WEB-INF/pages/shared/password.jsp");
params.put("AllowedRoles", "*");
// it's routing correctly to servlet, but it uses params from first registration,
// so that routing to jsp page is incorrect
serve("/changepassword").with(ContextForwarder.class, params);
}
}
The problem is that guice creates ContextForwarder servlet as a singleton with init parameters from the first registered method and then regardless of the request url it has parameters from the first registration. Is there any other solution to route user to different sites considering current user role? Is it possible to configure the same servlet class with two different configurations?
I have found a solution, however I am not fully satisfied with it. I found out that, in solution without guice, web container (tomcat) creates two separate servlets using the same servlet class and injecting different init parameters. Guice by default restricts servlets to be singletons, so to copy default behaviour from web.xml solution I needed to find a way to create two instance of the same class and register it twice with different parameters. I solved this by creating two sub-classes to my servlet class, both with empty body, then I registered them with different parameters.
This solution works, but it involve creating empty-body sub-classes which I am not satisfied with. It's not a problem when I got two sub-classes, but with more of them code is becoming cumbersome.

Categories

Resources